diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:25 +0000 |
commit | 5363f350887b1e5b5dd21a86f88c8af9d7fea6da (patch) | |
tree | 35ca005eb6e0e9a1ba3bb5dbc033209ad445dc17 /src/tools/rust-analyzer/crates/ide | |
parent | Adding debian version 1.66.0+dfsg1-1. (diff) | |
download | rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.tar.xz rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide')
10 files changed, 378 insertions, 120 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml index 712459a7e..73f202630 100644 --- a/src/tools/rust-analyzer/crates/ide/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" description = "TBD" license = "MIT OR Apache-2.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.65" [lib] doctest = false diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index d0be1b3f4..43f7a529b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -289,10 +289,10 @@ mod b; enum E { X(Foo$0) } //- /a.rs -struct Foo; - //^^^ +pub struct Foo; + //^^^ //- /b.rs -struct Foo; +pub struct Foo; "#, ); } @@ -1834,4 +1834,86 @@ fn f() { "#, ); } + + #[test] + fn goto_bin_op_multiple_impl() { + check( + r#" +//- minicore: add +struct S; +impl core::ops::Add for S { + fn add( + //^^^ + ) {} +} +impl core::ops::Add<usize> for S { + fn add( + ) {} +} + +fn f() { + S +$0 S +} +"#, + ); + + check( + r#" +//- minicore: add +struct S; +impl core::ops::Add for S { + fn add( + ) {} +} +impl core::ops::Add<usize> for S { + fn add( + //^^^ + ) {} +} + +fn f() { + S +$0 0usize +} +"#, + ); + } + + #[test] + fn path_call_multiple_trait_impl() { + check( + r#" +trait Trait<T> { + fn f(_: T); +} +impl Trait<i32> for usize { + fn f(_: i32) {} + //^ +} +impl Trait<i64> for usize { + fn f(_: i64) {} +} +fn main() { + usize::f$0(0i32); +} +"#, + ); + + check( + r#" +trait Trait<T> { + fn f(_: T); +} +impl Trait<i32> for usize { + fn f(_: i32) {} +} +impl Trait<i64> for usize { + fn f(_: i64) {} + //^ +} +fn main() { + usize::f$0(0i64); +} +"#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 3687b597f..838fb18c3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -119,7 +119,14 @@ pub(crate) fn hover( }); } - let in_attr = matches!(original_token.parent().and_then(ast::TokenTree::cast), Some(tt) if tt.syntax().ancestors().any(|it| ast::Meta::can_cast(it.kind()))); + let in_attr = original_token + .parent_ancestors() + .filter_map(ast::Item::cast) + .any(|item| sema.is_attr_macro_call(&item)) + && !matches!( + original_token.parent().and_then(ast::TokenTree::cast), + Some(tt) if tt.syntax().ancestors().any(|it| ast::Meta::can_cast(it.kind())) + ); // prefer descending the same token kind in attribute expansions, in normal macros text // equivalency is more important let descended = if in_attr { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 34d8bf67a..37384c4e7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -1,7 +1,10 @@ use std::fmt; use either::Either; -use hir::{known, Callable, HasVisibility, HirDisplay, Mutability, Semantics, TypeInfo}; +use hir::{ + known, Adjust, AutoBorrow, Callable, HasVisibility, HirDisplay, Mutability, OverloadedDeref, + PointerCast, Safety, Semantics, TypeInfo, +}; use ide_db::{ base_db::FileRange, famous_defs::FamousDefs, syntax_helpers::node_ext::walk_ty, FxHashMap, RootDatabase, @@ -22,7 +25,7 @@ pub struct InlayHintsConfig { pub type_hints: bool, pub parameter_hints: bool, pub chaining_hints: bool, - pub reborrow_hints: ReborrowHints, + pub adjustment_hints: AdjustmentHints, pub closure_return_type_hints: ClosureReturnTypeHints, pub binding_mode_hints: bool, pub lifetime_elision_hints: LifetimeElisionHints, @@ -48,9 +51,9 @@ pub enum LifetimeElisionHints { } #[derive(Clone, Debug, PartialEq, Eq)] -pub enum ReborrowHints { +pub enum AdjustmentHints { Always, - MutableOnly, + ReborrowOnly, Never, } @@ -61,7 +64,8 @@ pub enum InlayKind { ClosingBraceHint, ClosureReturnTypeHint, GenericParamListHint, - ImplicitReborrowHint, + AdjustmentHint, + AdjustmentHintClosingParenthesis, LifetimeHint, ParameterHint, TypeHint, @@ -115,6 +119,12 @@ impl From<String> for InlayHintLabel { } } +impl From<&str> for InlayHintLabel { + fn from(s: &str) -> Self { + Self { parts: vec![InlayHintLabelPart { text: s.into(), linked_location: None }] } + } +} + impl fmt::Display for InlayHintLabel { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.parts.iter().map(|part| &part.text).format("")) @@ -180,7 +190,7 @@ impl fmt::Debug for InlayHintLabelPart { pub(crate) fn inlay_hints( db: &RootDatabase, file_id: FileId, - range_limit: Option<FileRange>, + range_limit: Option<TextRange>, config: &InlayHintsConfig, ) -> Vec<InlayHint> { let _p = profile::span("inlay_hints"); @@ -195,7 +205,7 @@ pub(crate) fn inlay_hints( let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node); match range_limit { - Some(FileRange { range, .. }) => match file.covering_element(range) { + Some(range) => match file.covering_element(range) { NodeOrToken::Token(_) => return acc, NodeOrToken::Node(n) => n .descendants() @@ -221,6 +231,7 @@ fn hints( match node { ast::Expr(expr) => { chaining_hints(hints, sema, &famous_defs, config, file_id, &expr); + adjustment_hints(hints, sema, config, &expr); match expr { ast::Expr::CallExpr(it) => param_name_hints(hints, sema, config, ast::Expr::from(it)), ast::Expr::MethodCallExpr(it) => { @@ -229,7 +240,7 @@ fn hints( ast::Expr::ClosureExpr(it) => closure_ret_hints(hints, sema, &famous_defs, config, file_id, it), // We could show reborrows for all expressions, but usually that is just noise to the user // and the main point here is to show why "moving" a mutable reference doesn't necessarily move it - ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr), + // ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr), _ => None, } }, @@ -617,30 +628,95 @@ fn closure_ret_hints( Some(()) } -fn reborrow_hints( +fn adjustment_hints( acc: &mut Vec<InlayHint>, sema: &Semantics<'_, RootDatabase>, config: &InlayHintsConfig, expr: &ast::Expr, ) -> Option<()> { - if config.reborrow_hints == ReborrowHints::Never { + if config.adjustment_hints == AdjustmentHints::Never { + return None; + } + + if let ast::Expr::ParenExpr(_) = expr { + // These inherit from the inner expression which would result in duplicate hints return None; } + let parent = expr.syntax().parent().and_then(ast::Expr::cast); let descended = sema.descend_node_into_attributes(expr.clone()).pop(); let desc_expr = descended.as_ref().unwrap_or(expr); - let mutability = sema.is_implicit_reborrow(desc_expr)?; - let label = match mutability { - hir::Mutability::Shared if config.reborrow_hints != ReborrowHints::MutableOnly => "&*", - hir::Mutability::Mut => "&mut *", - _ => return None, + let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?; + let needs_parens = match parent { + Some(parent) => { + match parent { + ast::Expr::AwaitExpr(_) + | ast::Expr::CallExpr(_) + | ast::Expr::CastExpr(_) + | ast::Expr::FieldExpr(_) + | ast::Expr::MethodCallExpr(_) + | ast::Expr::TryExpr(_) => true, + // FIXME: shorthands need special casing, though not sure if adjustments are even valid there + ast::Expr::RecordExpr(_) => false, + ast::Expr::IndexExpr(index) => index.base().as_ref() == Some(expr), + _ => false, + } + } + None => false, }; - acc.push(InlayHint { - range: expr.syntax().text_range(), - kind: InlayKind::ImplicitReborrowHint, - label: label.to_string().into(), - tooltip: Some(InlayTooltip::String("Compiler inserted reborrow".into())), - }); + if needs_parens { + acc.push(InlayHint { + range: expr.syntax().text_range(), + kind: InlayKind::AdjustmentHint, + label: "(".into(), + tooltip: None, + }); + } + for adjustment in adjustments.into_iter().rev() { + // FIXME: Add some nicer tooltips to each of these + let text = match adjustment { + Adjust::NeverToAny if config.adjustment_hints == AdjustmentHints::Always => { + "<never-to-any>" + } + Adjust::Deref(None) => "*", + Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => "*", + Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => "*", + Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => "&", + Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => "&mut ", + Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => "&raw const ", + Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => "&raw mut ", + // some of these could be represented via `as` casts, but that's not too nice and + // handling everything as a prefix expr makes the `(` and `)` insertion easier + Adjust::Pointer(cast) if config.adjustment_hints == AdjustmentHints::Always => { + match cast { + PointerCast::ReifyFnPointer => "<fn-item-to-fn-pointer>", + PointerCast::UnsafeFnPointer => "<safe-fn-pointer-to-unsafe-fn-pointer>", + PointerCast::ClosureFnPointer(Safety::Unsafe) => { + "<closure-to-unsafe-fn-pointer>" + } + PointerCast::ClosureFnPointer(Safety::Safe) => "<closure-to-fn-pointer>", + PointerCast::MutToConstPointer => "<mut-ptr-to-const-ptr>", + PointerCast::ArrayToPointer => "<array-ptr-to-element-ptr>", + PointerCast::Unsize => "<unsize>", + } + } + _ => continue, + }; + acc.push(InlayHint { + range: expr.syntax().text_range(), + kind: InlayKind::AdjustmentHint, + label: text.into(), + tooltip: None, + }); + } + if needs_parens { + acc.push(InlayHint { + range: expr.syntax().text_range(), + kind: InlayKind::AdjustmentHintClosingParenthesis, + label: ")".into(), + tooltip: None, + }); + } Some(()) } @@ -1213,12 +1289,11 @@ fn get_callable( #[cfg(test)] mod tests { use expect_test::{expect, Expect}; - use ide_db::base_db::FileRange; use itertools::Itertools; use syntax::{TextRange, TextSize}; use test_utils::extract_annotations; - use crate::inlay_hints::ReborrowHints; + use crate::inlay_hints::AdjustmentHints; use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints}; use super::ClosureReturnTypeHints; @@ -1230,7 +1305,7 @@ mod tests { chaining_hints: false, lifetime_elision_hints: LifetimeElisionHints::Never, closure_return_type_hints: ClosureReturnTypeHints::Never, - reborrow_hints: ReborrowHints::Always, + adjustment_hints: AdjustmentHints::Never, binding_mode_hints: false, hide_named_constructor_hints: false, hide_closure_initialization_hints: false, @@ -1242,7 +1317,6 @@ mod tests { type_hints: true, parameter_hints: true, chaining_hints: true, - reborrow_hints: ReborrowHints::Always, closure_return_type_hints: ClosureReturnTypeHints::WithBlock, binding_mode_hints: true, lifetime_elision_hints: LifetimeElisionHints::Always, @@ -1838,10 +1912,7 @@ fn main() { .inlay_hints( &InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG }, file_id, - Some(FileRange { - file_id, - range: TextRange::new(TextSize::from(500), TextSize::from(600)), - }), + Some(TextRange::new(TextSize::from(500), TextSize::from(600))), ) .unwrap(); let actual = @@ -2846,48 +2917,6 @@ impl () { } #[test] - fn hints_implicit_reborrow() { - check_with_config( - InlayHintsConfig { - reborrow_hints: ReborrowHints::Always, - parameter_hints: true, - ..DISABLED_CONFIG - }, - r#" -fn __() { - let unique = &mut (); - let r_mov = unique; - let foo: &mut _ = unique; - //^^^^^^ &mut * - ref_mut_id(unique); - //^^^^^^ mut_ref - //^^^^^^ &mut * - let shared = ref_id(unique); - //^^^^^^ shared_ref - //^^^^^^ &* - let mov = shared; - let r_mov: &_ = shared; - ref_id(shared); - //^^^^^^ shared_ref - - identity(unique); - identity(shared); -} -fn identity<T>(t: T) -> T { - t -} -fn ref_mut_id(mut_ref: &mut ()) -> &mut () { - mut_ref - //^^^^^^^ &mut * -} -fn ref_id(shared_ref: &()) -> &() { - shared_ref -} -"#, - ); - } - - #[test] fn hints_binding_modes() { check_with_config( InlayHintsConfig { binding_mode_hints: true, ..DISABLED_CONFIG }, @@ -2994,4 +3023,76 @@ fn f() { "#, ); } + + #[test] + fn adjustment_hints() { + check_with_config( + InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG }, + r#" +//- minicore: coerce_unsized +fn main() { + let _: u32 = loop {}; + //^^^^^^^<never-to-any> + let _: &u32 = &mut 0; + //^^^^^^& + //^^^^^^* + let _: &mut u32 = &mut 0; + //^^^^^^&mut $ + //^^^^^^* + let _: *const u32 = &mut 0; + //^^^^^^&raw const $ + //^^^^^^* + let _: *mut u32 = &mut 0; + //^^^^^^&raw mut $ + //^^^^^^* + let _: fn() = main; + //^^^^<fn-item-to-fn-pointer> + let _: unsafe fn() = main; + //^^^^<safe-fn-pointer-to-unsafe-fn-pointer> + //^^^^<fn-item-to-fn-pointer> + let _: unsafe fn() = main as fn(); + //^^^^^^^^^^^^<safe-fn-pointer-to-unsafe-fn-pointer> + let _: fn() = || {}; + //^^^^^<closure-to-fn-pointer> + let _: unsafe fn() = || {}; + //^^^^^<closure-to-unsafe-fn-pointer> + let _: *const u32 = &mut 0u32 as *mut u32; + //^^^^^^^^^^^^^^^^^^^^^<mut-ptr-to-const-ptr> + let _: &mut [_] = &mut [0; 0]; + //^^^^^^^^^^^<unsize> + //^^^^^^^^^^^&mut $ + //^^^^^^^^^^^* + + Struct.consume(); + Struct.by_ref(); + //^^^^^^( + //^^^^^^& + //^^^^^^) + Struct.by_ref_mut(); + //^^^^^^( + //^^^^^^&mut $ + //^^^^^^) + + (&Struct).consume(); + //^^^^^^^* + (&Struct).by_ref(); + + (&mut Struct).consume(); + //^^^^^^^^^^^* + (&mut Struct).by_ref(); + //^^^^^^^^^^^& + //^^^^^^^^^^^* + (&mut Struct).by_ref_mut(); +} + +#[derive(Copy, Clone)] +struct Struct; +impl Struct { + fn consume(self) {} + fn by_ref(&self) {} + fn by_ref_mut(&mut self) {} +} +"#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 416817ca0..7402e86f3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -81,8 +81,8 @@ pub use crate::{ highlight_related::{HighlightRelatedConfig, HighlightedRange}, hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult}, inlay_hints::{ - ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, - InlayTooltip, LifetimeElisionHints, ReborrowHints, + AdjustmentHints, ClosureReturnTypeHints, InlayHint, InlayHintLabel, InlayHintsConfig, + InlayKind, InlayTooltip, LifetimeElisionHints, }, join_lines::JoinLinesConfig, markup::Markup, @@ -367,7 +367,7 @@ impl Analysis { &self, config: &InlayHintsConfig, file_id: FileId, - range: Option<FileRange>, + range: Option<TextRange>, ) -> Cancellable<Vec<InlayHint>> { self.with_db(|db| inlay_hints::inlay_hints(db, file_id, range, config)) } diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 852a8fd83..fcbf6d8e5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -1,9 +1,9 @@ //! This module generates [moniker](https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/#exportsImports) //! for LSIF and LSP. -use hir::{db::DefDatabase, AsAssocItem, AssocItemContainer, Crate, Name, Semantics}; +use hir::{AsAssocItem, AssocItemContainer, Crate, Name, Semantics}; use ide_db::{ - base_db::{CrateOrigin, FileId, FileLoader, FilePosition, LangCrateOrigin}, + base_db::{CrateOrigin, FilePosition, LangCrateOrigin}, defs::{Definition, IdentClass}, helpers::pick_best_token, RootDatabase, @@ -11,7 +11,7 @@ use ide_db::{ use itertools::Itertools; use syntax::{AstNode, SyntaxKind::*, T}; -use crate::{doc_links::token_as_doc_comment, RangeInfo}; +use crate::{doc_links::token_as_doc_comment, parent_module::crates_for, RangeInfo}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum MonikerDescriptorKind { @@ -73,20 +73,8 @@ impl MonikerResult { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PackageInformation { pub name: String, - pub repo: String, - pub version: String, -} - -pub(crate) fn crate_for_file(db: &RootDatabase, file_id: FileId) -> Option<Crate> { - for &krate in db.relevant_crates(file_id).iter() { - let crate_def_map = db.crate_def_map(krate); - for (_, data) in crate_def_map.modules() { - if data.origin.file_id() == Some(file_id) { - return Some(krate.into()); - } - } - } - None + pub repo: Option<String>, + pub version: Option<String>, } pub(crate) fn moniker( @@ -95,7 +83,7 @@ pub(crate) fn moniker( ) -> Option<RangeInfo<Vec<MonikerResult>>> { let sema = &Semantics::new(db); let file = sema.parse(file_id).syntax().clone(); - let current_crate = crate_for_file(db, file_id)?; + let current_crate: hir::Crate = crates_for(db, file_id).pop()?.into(); let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind { IDENT | INT_NUMBER @@ -256,18 +244,18 @@ pub(crate) fn def_to_moniker( let (name, repo, version) = match krate.origin(db) { CrateOrigin::CratesIo { repo, name } => ( name.unwrap_or(krate.display_name(db)?.canonical_name().to_string()), - repo?, - krate.version(db)?, + repo, + krate.version(db), ), CrateOrigin::Lang(lang) => ( krate.display_name(db)?.canonical_name().to_string(), - "https://github.com/rust-lang/rust/".to_string(), - match lang { + Some("https://github.com/rust-lang/rust/".to_string()), + Some(match lang { LangCrateOrigin::Other => { "https://github.com/rust-lang/rust/library/".into() } lang => format!("https://github.com/rust-lang/rust/library/{lang}",), - }, + }), ), }; PackageInformation { name, repo, version } @@ -315,7 +303,7 @@ pub mod module { } "#, "foo::module::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Import, ); check_moniker( @@ -331,7 +319,7 @@ pub mod module { } "#, "foo::module::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -348,7 +336,7 @@ pub mod module { } "#, "foo::module::MyTrait::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -365,7 +353,7 @@ pub mod module { } "#, "foo::module::MyTrait::MY_CONST", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -382,7 +370,7 @@ pub mod module { } "#, "foo::module::MyTrait::MyType", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -405,7 +393,7 @@ pub mod module { } "#, "foo::module::MyStruct::MyTrait::func", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Export, ); } @@ -425,7 +413,7 @@ pub struct St { } "#, "foo::St::a", - r#"PackageInformation { name: "foo", repo: "https://a.b/foo.git", version: "0.1.0" }"#, + r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#, MonikerKind::Import, ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs index e942413c1..0f758cfa2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/references.rs +++ b/src/tools/rust-analyzer/crates/ide/src/references.rs @@ -16,6 +16,7 @@ use ide_db::{ search::{ReferenceCategory, SearchScope, UsageSearchResult}, RootDatabase, }; +use itertools::Itertools; use stdx::hash::NoHashHashMap; use syntax::{ algo::find_node_at_offset, @@ -86,6 +87,7 @@ pub(crate) fn find_all_refs( file_id, refs.into_iter() .map(|file_ref| (file_ref.range, file_ref.category)) + .unique() .collect(), ) }) diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index fe44856dc..b4df04370 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -40,7 +40,9 @@ pub(crate) fn prepare_rename( if def.range_for_rename(&sema).is_none() { bail!("No references found at position") } - let frange = sema.original_range(name_like.syntax()); + let Some(frange) = sema.original_range_opt(name_like.syntax()) else { + bail!("No references found at position"); + }; always!( frange.range.contains_inclusive(position.offset) @@ -51,7 +53,7 @@ pub(crate) fn prepare_rename( .reduce(|acc, cur| match (acc, cur) { // ensure all ranges are the same (Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner), - (Err(e), _) => Err(e), + (e @ Err(_), _) | (_, e @ Err(_)) => e, _ => bail!("inconsistent text range"), }); @@ -2249,4 +2251,33 @@ fn foo((bar | bar | bar): ()) { "#, ); } + + #[test] + fn regression_13498() { + check( + "Testing", + r" +mod foo { + pub struct Test$0; +} + +use foo::Test as Tester; + +fn main() { + let t = Tester; +} +", + r" +mod foo { + pub struct Testing; +} + +use foo::Testing as Tester; + +fn main() { + let t = Tester; +} +", + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index fedc1a435..e7412d27f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -149,7 +149,7 @@ fn signature_help_for_call( variant.name(db) ); } - hir::CallableKind::Closure | hir::CallableKind::FnPtr => (), + hir::CallableKind::Closure | hir::CallableKind::FnPtr | hir::CallableKind::Other => (), } res.signature.push('('); @@ -189,9 +189,10 @@ fn signature_help_for_call( hir::CallableKind::Function(func) if callable.return_type().contains_unknown() => { render(func.ret_type(db)) } - hir::CallableKind::Function(_) | hir::CallableKind::Closure | hir::CallableKind::FnPtr => { - render(callable.return_type()) - } + hir::CallableKind::Function(_) + | hir::CallableKind::Closure + | hir::CallableKind::FnPtr + | hir::CallableKind::Other => render(callable.return_type()), hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {} } Some(res) @@ -387,10 +388,9 @@ mod tests { } fn check(ra_fixture: &str, expect: Expect) { - // Implicitly add `Sized` to avoid noisy `T: ?Sized` in the results. let fixture = format!( r#" -#[lang = "sized"] trait Sized {{}} +//- minicore: sized, fn {ra_fixture} "# ); @@ -1331,4 +1331,50 @@ fn f() { "#]], ); } + + #[test] + fn help_for_generic_call() { + check( + r#" +fn f<F: FnOnce(u8, u16) -> i32>(f: F) { + f($0) +} +"#, + expect![[r#" + (u8, u16) -> i32 + ^^ --- + "#]], + ); + check( + r#" +fn f<T, F: FnOnce(&T, u16) -> &T>(f: F) { + f($0) +} +"#, + expect![[r#" + (&T, u16) -> &T + ^^ --- + "#]], + ); + } + + #[test] + fn regression_13579() { + check( + r#" +fn f() { + take(2)($0); +} + +fn take<C, Error>( + count: C +) -> impl Fn() -> C { + move || count +} +"#, + expect![[r#" + () -> i32 + "#]], + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index 27ad1a948..2380cf738 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -13,7 +13,8 @@ use syntax::{AstNode, SyntaxKind::*, SyntaxToken, TextRange, T}; use crate::{ hover::hover_for_definition, - moniker::{crate_for_file, def_to_moniker, MonikerResult}, + moniker::{def_to_moniker, MonikerResult}, + parent_module::crates_for, Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig, TryToNav, }; @@ -99,7 +100,7 @@ fn all_modules(db: &dyn HirDatabase) -> Vec<Module> { impl StaticIndex<'_> { fn add_file(&mut self, file_id: FileId) { - let current_crate = crate_for_file(self.db, file_id); + let current_crate = crates_for(self.db, file_id).pop().map(Into::into); let folds = self.analysis.folding_ranges(file_id).unwrap(); let inlay_hints = self .analysis @@ -111,7 +112,7 @@ impl StaticIndex<'_> { chaining_hints: true, closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock, lifetime_elision_hints: crate::LifetimeElisionHints::Never, - reborrow_hints: crate::ReborrowHints::Never, + adjustment_hints: crate::AdjustmentHints::Never, hide_named_constructor_hints: false, hide_closure_initialization_hints: false, param_names_for_lifetime_elision_hints: false, |