diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index 4e57845a694d1..68e0a8bc693a1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -1,6 +1,9 @@ //! An algorithm to find a path to refer to a certain item. -use std::{cmp::Ordering, iter}; +use std::{ + cmp::Ordering, + iter::{self, once}, +}; use hir_expand::{ name::{known, AsName, Name}, @@ -14,35 +17,29 @@ use crate::{ nameres::DefMap, path::{ModPath, PathKind}, visibility::{Visibility, VisibilityExplicitness}, - CrateRootModuleId, ModuleDefId, ModuleId, + ModuleDefId, ModuleId, }; /// Find a path that can be used to refer to a certain item. This can depend on /// *from where* you're referring to the item, hence the `from` parameter. pub fn find_path( - db: &dyn DefDatabase, - item: ItemInNs, - from: ModuleId, - prefer_no_std: bool, - prefer_prelude: bool, -) -> Option { - let _p = tracing::span!(tracing::Level::INFO, "find_path").entered(); - find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from) -} - -/// Find a path that can be used to refer to a certain item. This can depend on -/// *from where* you're referring to the item, hence the `from` parameter. -pub fn find_path_prefixed( db: &dyn DefDatabase, item: ItemInNs, from: ModuleId, prefix_kind: PrefixKind, + ignore_local_imports: bool, prefer_no_std: bool, prefer_prelude: bool, ) -> Option { - let _p = tracing::span!(tracing::Level::INFO, "find_path_prefixed").entered(); + let _p = tracing::span!(tracing::Level::INFO, "find_path").entered(); find_path_inner( - FindPathCtx { db, prefixed: Some(prefix_kind), prefer_no_std, prefer_prelude }, + FindPathCtx { + db, + prefix: prefix_kind, + prefer_no_std, + prefer_prelude, + ignore_local_imports, + }, item, from, ) @@ -70,7 +67,7 @@ pub enum PrefixKind { /// This is the same as plain, just that paths will start with `self` prepended if the path /// starts with an identifier that is not a crate. BySelf, - /// Causes paths to ignore imports in the local module. + /// Causes paths to not use a self, super or crate prefix. Plain, /// Causes paths to start with `crate` where applicable, effectively forcing paths to be absolute. ByCrate, @@ -78,37 +75,33 @@ pub enum PrefixKind { impl PrefixKind { #[inline] - fn prefix(self) -> PathKind { + fn path_kind(self) -> PathKind { match self { PrefixKind::BySelf => PathKind::Super(0), PrefixKind::Plain => PathKind::Plain, PrefixKind::ByCrate => PathKind::Crate, } } - - #[inline] - fn is_absolute(&self) -> bool { - self == &PrefixKind::ByCrate - } } #[derive(Copy, Clone)] struct FindPathCtx<'db> { db: &'db dyn DefDatabase, - prefixed: Option, + prefix: PrefixKind, prefer_no_std: bool, prefer_prelude: bool, + ignore_local_imports: bool, } /// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Option { // - if the item is a builtin, it's in scope if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item { - return Some(ModPath::from_segments(PathKind::Plain, Some(builtin.as_name()))); + return Some(ModPath::from_segments(PathKind::Plain, once(builtin.as_name()))); } let def_map = from.def_map(ctx.db); - let crate_root = def_map.crate_root(); + let crate_root = from.derive_crate_root(); // - if the item is a module, jump straight to module search if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item { let mut visited_modules = FxHashSet::default(); @@ -119,7 +112,6 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti }, &def_map, &mut visited_modules, - crate_root, from, module_id, MAX_PATH_LEN, @@ -127,11 +119,20 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti .map(|(item, _)| item); } - // - if the item is already in scope, return the name under which it is - let scope_name = find_in_scope(ctx.db, &def_map, from, item); - if ctx.prefixed.is_none() { + let prefix = if item.module(ctx.db).is_some_and(|it| it.is_within_block()) { + PrefixKind::Plain + } else { + ctx.prefix + }; + let may_be_in_scope = match prefix { + PrefixKind::Plain | PrefixKind::BySelf => true, + PrefixKind::ByCrate => from.is_crate_root(), + }; + if may_be_in_scope { + // - if the item is already in scope, return the name under which it is + let scope_name = find_in_scope(ctx.db, &def_map, from, item, ctx.ignore_local_imports); if let Some(scope_name) = scope_name { - return Some(ModPath::from_segments(PathKind::Plain, Some(scope_name))); + return Some(ModPath::from_segments(prefix.path_kind(), Some(scope_name))); } } @@ -164,11 +165,9 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti }, &def_map, &mut visited_modules, - crate_root, MAX_PATH_LEN, item, from, - scope_name, ) .map(|(item, _)| item) } @@ -178,7 +177,6 @@ fn find_path_for_module( ctx: FindPathCtx<'_>, def_map: &DefMap, visited_modules: &mut FxHashSet, - crate_root: CrateRootModuleId, from: ModuleId, module_id: ModuleId, max_len: usize, @@ -187,38 +185,25 @@ fn find_path_for_module( return None; } - // Base cases: - // - if the item is already in scope, return the name under which it is - let scope_name = find_in_scope(ctx.db, def_map, from, ItemInNs::Types(module_id.into())); - if ctx.prefixed.is_none() { - if let Some(scope_name) = scope_name { - return Some((ModPath::from_segments(PathKind::Plain, Some(scope_name)), Stable)); - } - } - + let is_crate_root = module_id.as_crate_root(); // - if the item is the crate root, return `crate` - if module_id == crate_root { + if is_crate_root.is_some_and(|it| it == from.derive_crate_root()) { return Some((ModPath::from_segments(PathKind::Crate, None), Stable)); } - // - if relative paths are fine, check if we are searching for a parent - if ctx.prefixed.filter(PrefixKind::is_absolute).is_none() { - if let modpath @ Some(_) = find_self_super(def_map, module_id, from) { - return modpath.zip(Some(Stable)); - } - } - + let root_def_map = from.derive_crate_root().def_map(ctx.db); // - if the item is the crate root of a dependency crate, return the name from the extern prelude - let root_def_map = crate_root.def_map(ctx.db); - for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() { - if module_id == def_id { - let name = scope_name.unwrap_or_else(|| name.clone()); - + if let Some(crate_root) = is_crate_root { + // rev here so we prefer looking at renamed extern decls first + for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude().rev() { + if crate_root != def_id { + continue; + } let name_already_occupied_in_type_ns = def_map .with_ancestor_maps(ctx.db, from.local_id, &mut |def_map, local_id| { def_map[local_id] .scope - .type_(&name) + .type_(name) .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id.into())) }) .is_some(); @@ -228,24 +213,48 @@ fn find_path_for_module( } else { PathKind::Plain }; - return Some((ModPath::from_segments(kind, Some(name)), Stable)); + return Some((ModPath::from_segments(kind, once(name.clone())), Stable)); + } + } + let prefix = if module_id.is_within_block() { PrefixKind::Plain } else { ctx.prefix }; + let may_be_in_scope = match prefix { + PrefixKind::Plain | PrefixKind::BySelf => true, + PrefixKind::ByCrate => from.is_crate_root(), + }; + if may_be_in_scope { + let scope_name = find_in_scope( + ctx.db, + def_map, + from, + ItemInNs::Types(module_id.into()), + ctx.ignore_local_imports, + ); + if let Some(scope_name) = scope_name { + // - if the item is already in scope, return the name under which it is + return Some((ModPath::from_segments(prefix.path_kind(), once(scope_name)), Stable)); } } - if let value @ Some(_) = + // - if the module can be referenced as self, super or crate, do that + if let Some(mod_path) = is_kw_kind_relative_to_from(def_map, module_id, from) { + if ctx.prefix != PrefixKind::ByCrate || mod_path.kind == PathKind::Crate { + return Some((mod_path, Stable)); + } + } + + // - if the module is in the prelude, return it by that path + if let Some(mod_path) = find_in_prelude(ctx.db, &root_def_map, def_map, ItemInNs::Types(module_id.into()), from) { - return value.zip(Some(Stable)); + return Some((mod_path, Stable)); } calculate_best_path( ctx, def_map, visited_modules, - crate_root, max_len, ItemInNs::Types(module_id.into()), from, - scope_name, ) } @@ -255,9 +264,13 @@ fn find_in_scope( def_map: &DefMap, from: ModuleId, item: ItemInNs, + ignore_local_imports: bool, ) -> Option { + // FIXME: We could have multiple applicable names here, but we currently only return the first def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| { - def_map[local_id].scope.names_of(item, |name, _, _| Some(name.clone())) + def_map[local_id].scope.names_of(item, |name, _, declared| { + (declared || !ignore_local_imports).then(|| name.clone()) + }) }) } @@ -292,21 +305,32 @@ fn find_in_prelude( }); if found_and_same_def.unwrap_or(true) { - Some(ModPath::from_segments(PathKind::Plain, Some(name.clone()))) + Some(ModPath::from_segments(PathKind::Plain, once(name.clone()))) } else { None } } -fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option { +fn is_kw_kind_relative_to_from( + def_map: &DefMap, + item: ModuleId, + from: ModuleId, +) -> Option { + if item.krate != from.krate || item.is_within_block() || from.is_within_block() { + return None; + } + let item = item.local_id; + let from = from.local_id; if item == from { // - if the item is the module we're in, use `self` Some(ModPath::from_segments(PathKind::Super(0), None)) - } else if let Some(parent_id) = def_map[from.local_id].parent { - // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) - let parent_id = def_map.module_id(parent_id); + } else if let Some(parent_id) = def_map[from].parent { if item == parent_id { - Some(ModPath::from_segments(PathKind::Super(1), None)) + // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) + Some(ModPath::from_segments( + if parent_id == DefMap::ROOT { PathKind::Crate } else { PathKind::Super(1) }, + None, + )) } else { None } @@ -320,11 +344,9 @@ fn calculate_best_path( ctx: FindPathCtx<'_>, def_map: &DefMap, visited_modules: &mut FxHashSet, - crate_root: CrateRootModuleId, max_len: usize, item: ItemInNs, from: ModuleId, - scope_name: Option, ) -> Option<(ModPath, Stability)> { if max_len <= 1 { return None; @@ -346,14 +368,12 @@ fn calculate_best_path( // dependency in this case. for (module_id, name) in find_local_import_locations(ctx.db, item, from) { if !visited_modules.insert(module_id) { - cov_mark::hit!(recursive_imports); continue; } if let Some(mut path) = find_path_for_module( ctx, def_map, visited_modules, - crate_root, from, module_id, best_path_len - 1, @@ -390,7 +410,6 @@ fn calculate_best_path( ctx, def_map, visited_modules, - crate_root, from, info.container, max_len - 1, @@ -418,19 +437,7 @@ fn calculate_best_path( } } } - let mut prefixed = ctx.prefixed; - if let Some(module) = item.module(ctx.db) { - if module.containing_block().is_some() && ctx.prefixed.is_some() { - cov_mark::hit!(prefixed_in_block_expression); - prefixed = Some(PrefixKind::Plain); - } - } - match prefixed.map(PrefixKind::prefix) { - Some(prefix) => best_path.or_else(|| { - scope_name.map(|scope_name| (ModPath::from_segments(prefix, Some(scope_name)), Stable)) - }), - None => best_path, - } + best_path } /// Select the best (most relevant) path between two paths. @@ -535,7 +542,6 @@ fn find_local_import_locations( if !seen.insert(module) { continue; // already processed this module } - let ext_def_map; let data = if module.krate == from.krate { if module.block.is_some() { @@ -571,7 +577,7 @@ fn find_local_import_locations( // what the user wants; and if this module can import // the item and we're a submodule of it, so can we. // Also this keeps the cached data smaller. - if is_pub_or_explicit || declared { + if declared || is_pub_or_explicit { locations.push((module, name.clone())); } } @@ -605,8 +611,9 @@ mod tests { fn check_found_path_( ra_fixture: &str, path: &str, - prefix_kind: Option, + prefix_kind: PrefixKind, prefer_prelude: bool, + ignore_local_imports: bool, ) { let (db, pos) = TestDB::with_position(ra_fixture); let module = db.module_at_position(pos); @@ -628,43 +635,51 @@ mod tests { crate::item_scope::BuiltinShadowMode::Module, None, ) - .0 + .0; + let resolved = resolved .take_types() - .expect("path does not resolve to a type"); + .map(ItemInNs::Types) + .or_else(|| resolved.take_values().map(ItemInNs::Values)) + .expect("path does not resolve to a type or value"); let found_path = find_path_inner( - FindPathCtx { prefer_no_std: false, db: &db, prefixed: prefix_kind, prefer_prelude }, - ItemInNs::Types(resolved), + FindPathCtx { + prefer_no_std: false, + db: &db, + prefix: prefix_kind, + prefer_prelude, + ignore_local_imports, + }, + resolved, module, ); - assert_eq!(found_path, Some(mod_path), "on kind: {prefix_kind:?}"); + assert_eq!(found_path, Some(mod_path), "on kind: {prefix_kind:?} ({ignore_local_imports})"); } - #[track_caller] fn check_found_path( ra_fixture: &str, - unprefixed: &str, - prefixed: &str, - absolute: &str, - self_prefixed: &str, + plain_non_local: &str, + plain: &str, + by_crate: &str, + by_self: &str, ) { - check_found_path_(ra_fixture, unprefixed, None, false); - check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain), false); - check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate), false); - check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf), false); + check_found_path_(ra_fixture, plain_non_local, PrefixKind::Plain, false, true); + check_found_path_(ra_fixture, plain, PrefixKind::Plain, false, false); + check_found_path_(ra_fixture, by_crate, PrefixKind::ByCrate, false, false); + check_found_path_(ra_fixture, by_self, PrefixKind::BySelf, false, false); } fn check_found_path_prelude( ra_fixture: &str, - unprefixed: &str, - prefixed: &str, - absolute: &str, - self_prefixed: &str, + plain_non_local: &str, + plain: &str, + by_crate: &str, + by_self: &str, ) { - check_found_path_(ra_fixture, unprefixed, None, true); - check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain), true); - check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate), true); - check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf), true); + check_found_path_(ra_fixture, plain_non_local, PrefixKind::Plain, true, true); + check_found_path_(ra_fixture, plain, PrefixKind::Plain, true, false); + check_found_path_(ra_fixture, by_crate, PrefixKind::ByCrate, true, false); + check_found_path_(ra_fixture, by_self, PrefixKind::BySelf, true, false); } #[test] @@ -831,10 +846,10 @@ pub mod ast { } } "#, - "ast::ModuleItem", - "syntax::ast::ModuleItem", - "syntax::ast::ModuleItem", "syntax::ast::ModuleItem", + "ast::ModuleItem", + "crate::ast::ModuleItem", + "self::ast::ModuleItem", ); check_found_path( @@ -965,8 +980,8 @@ pub mod prelude { "#, "S", "S", - "S", - "S", + "crate::S", + "self::S", ); } @@ -1271,12 +1286,11 @@ fn main() { #[test] fn inner_items_from_inner_module() { - cov_mark::check!(prefixed_in_block_expression); check_found_path( r#" fn main() { mod module { - struct Struct {} + pub struct Struct {} } { $0 @@ -1303,11 +1317,10 @@ fn main() { $0 } "#, - // FIXME: these could use fewer/better prefixes + "module::CompleteMe", "module::CompleteMe", "crate::module::CompleteMe", - "crate::module::CompleteMe", - "crate::module::CompleteMe", + "self::module::CompleteMe", ) } @@ -1358,7 +1371,6 @@ mod bar { #[test] fn recursive_pub_mod_reexport() { - cov_mark::check!(recursive_imports); check_found_path( r#" fn main() { @@ -1587,4 +1599,25 @@ pub mod prelude { "petgraph::graph::NodeIndex", ); } + + #[test] + fn regression_17271() { + check_found_path( + r#" +//- /lib.rs crate:main +mod foo; + +//- /foo.rs +mod bar; + +pub fn b() {$0} +//- /foo/bar.rs +pub fn c() {} +"#, + "bar::c", + "bar::c", + "crate::foo::bar::c", + "self::bar::c", + ); + } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index faa1eed15a45a..6e40293dbf8e6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -1,13 +1,12 @@ //! A map of all publicly exported items in a crate. -use std::{fmt, hash::BuildHasherDefault}; +use std::fmt; use base_db::CrateId; use fst::{raw::IndexedValue, Automaton, Streamer}; use hir_expand::name::Name; -use indexmap::IndexMap; use itertools::Itertools; -use rustc_hash::{FxHashSet, FxHasher}; +use rustc_hash::FxHashSet; use smallvec::SmallVec; use stdx::{format_to, TupleExt}; use triomphe::Arc; @@ -17,7 +16,7 @@ use crate::{ item_scope::{ImportOrExternCrate, ItemInNs}, nameres::DefMap, visibility::Visibility, - AssocItemId, ModuleDefId, ModuleId, TraitId, + AssocItemId, FxIndexMap, ModuleDefId, ModuleId, TraitId, }; /// Item import details stored in the `ImportMap`. @@ -58,7 +57,6 @@ enum IsTraitAssocItem { No, } -type FxIndexMap = IndexMap>; type ImportMapIndex = FxIndexMap, IsTraitAssocItem)>; impl ImportMap { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 54cd57110ea84..9c7dfa05b0e4f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -295,7 +295,7 @@ impl ItemScope { pub(crate) fn names_of( &self, item: ItemInNs, - mut cb: impl FnMut(&Name, Visibility, bool) -> Option, + mut cb: impl FnMut(&Name, Visibility, /*declared*/ bool) -> Option, ) -> Option { match item { ItemInNs::Macros(def) => self diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 88d4572196cde..ca8cc1c3ead13 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -106,6 +106,9 @@ use crate::{ }, }; +type FxIndexMap = + indexmap::IndexMap>; + #[derive(Debug)] pub struct ItemLoc { pub container: ModuleId, @@ -455,6 +458,26 @@ impl ModuleId { pub fn is_block_module(self) -> bool { self.block.is_some() && self.local_id == DefMap::ROOT } + + pub fn is_within_block(self) -> bool { + self.block.is_some() + } + + pub fn as_crate_root(&self) -> Option { + if self.local_id == DefMap::ROOT && self.block.is_none() { + Some(CrateRootModuleId { krate: self.krate }) + } else { + None + } + } + + pub fn derive_crate_root(&self) -> CrateRootModuleId { + CrateRootModuleId { krate: self.krate } + } + + fn is_crate_root(&self) -> bool { + self.local_id == DefMap::ROOT && self.block.is_none() + } } impl PartialEq for ModuleId { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index a528c4cc6972d..a66c0585a3680 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -81,7 +81,7 @@ use crate::{ per_ns::PerNs, visibility::{Visibility, VisibilityExplicitness}, AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId, - LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, + FxIndexMap, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId, }; /// Contains the results of (early) name resolution. @@ -129,7 +129,7 @@ pub struct DefMap { #[derive(Clone, Debug, PartialEq, Eq)] struct DefMapCrateData { /// The extern prelude which contains all root modules of external crates that are in scope. - extern_prelude: FxHashMap)>, + extern_prelude: FxIndexMap)>, /// Side table for resolving derive helpers. exported_derives: FxHashMap>, @@ -155,7 +155,7 @@ struct DefMapCrateData { impl DefMapCrateData { fn new(edition: Edition) -> Self { Self { - extern_prelude: FxHashMap::default(), + extern_prelude: FxIndexMap::default(), exported_derives: FxHashMap::default(), fn_proc_macro_mapping: FxHashMap::default(), proc_macro_loading_error: None, @@ -578,7 +578,8 @@ impl DefMap { pub(crate) fn extern_prelude( &self, - ) -> impl Iterator))> + '_ { + ) -> impl DoubleEndedIterator))> + '_ + { self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 1602b173858d9..9794963203bca 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -1,12 +1,11 @@ //! Name resolution façade. -use std::{fmt, hash::BuildHasherDefault, iter, mem}; +use std::{fmt, iter, mem}; use base_db::CrateId; use hir_expand::{ name::{name, Name}, MacroDefId, }; -use indexmap::IndexMap; use intern::Interned; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; @@ -27,10 +26,10 @@ use crate::{ type_ref::LifetimeRef, visibility::{RawVisibility, Visibility}, AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, - ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, - ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, - MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, - TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, + ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, + ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, + MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, + TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId, }; #[derive(Debug, Clone)] @@ -957,7 +956,6 @@ fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option)> { Some((res, import)) } -type FxIndexMap = IndexMap>; #[derive(Default)] struct ScopeNames { map: FxIndexMap>, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index c010f5d22b681..82bbc28884e16 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -13,7 +13,7 @@ use either::Either; use hir_def::{ data::adt::VariantData, db::DefDatabase, - find_path, + find_path::{self, PrefixKind}, generics::{TypeOrConstParamData, TypeParamProvenance}, item_scope::ItemInNs, lang_item::{LangItem, LangItemTarget}, @@ -999,6 +999,8 @@ impl HirDisplay for Ty { db.upcast(), ItemInNs::Types((*def_id).into()), module_id, + PrefixKind::Plain, + false, false, true, ) { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 85f33a10fcb2d..773ac01e0e3f8 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -789,7 +789,7 @@ impl Module { /// Finds a path that can be used to refer to the given item from within /// this module, if possible. - pub fn find_use_path( + pub fn find_path( self, db: &dyn DefDatabase, item: impl Into, @@ -800,6 +800,8 @@ impl Module { db, item.into().into(), self.into(), + PrefixKind::Plain, + false, prefer_no_std, prefer_prelude, ) @@ -807,7 +809,7 @@ impl Module { /// Finds a path that can be used to refer to the given item from within /// this module, if possible. This is used for returning import paths for use-statements. - pub fn find_use_path_prefixed( + pub fn find_use_path( self, db: &dyn DefDatabase, item: impl Into, @@ -815,11 +817,12 @@ impl Module { prefer_no_std: bool, prefer_prelude: bool, ) -> Option { - hir_def::find_path::find_path_prefixed( + hir_def::find_path::find_path( db, item.into().into(), self.into(), prefix_kind, + true, prefer_no_std, prefer_prelude, ) diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs index 9f56a1ee55d3b..45c0dd8da75fb 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs @@ -33,16 +33,11 @@ fn mod_item_path( }); let m = sema_scope.module(); - match name_hit_count { - Some(0..=1) | None => m.find_use_path(db.upcast(), *def, prefer_no_std, prefer_prelude), - Some(_) => m.find_use_path_prefixed( - db.upcast(), - *def, - PrefixKind::ByCrate, - prefer_no_std, - prefer_prelude, - ), - } + let prefix = match name_hit_count { + Some(0..=1) | None => PrefixKind::Plain, + Some(_) => PrefixKind::ByCrate, + }; + m.find_use_path(db.upcast(), *def, prefix, prefer_no_std, prefer_prelude) } /// Helper function to get path to `ModuleDef` as string diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 5ef374506ecc2..8eddc562bef46 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -462,7 +462,7 @@ fn build_pat( ) -> Option { match var { ExtendedVariant::Variant(var) => { - let path = mod_path_to_ast(&module.find_use_path( + let path = mod_path_to_ast(&module.find_path( db, ModuleDef::from(var), prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs index fd3a0506ab677..df87e2d044985 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -341,7 +341,7 @@ fn augment_references_with_imports( let import_scope = ImportScope::find_insert_use_container(name.syntax(), &ctx.sema); let path = ref_module - .find_use_path_prefixed( + .find_use_path( ctx.sema.db, ModuleDef::Module(*target_module), ctx.config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs index d649f13d6ee35..e0e2ac758533c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs @@ -50,7 +50,7 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) - _ => return None, }; - mod_path_to_ast(&module.find_use_path( + mod_path_to_ast(&module.find_path( ctx.db(), src_type_def, ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs index 41366658a74bf..367cf0bc8b96d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -201,7 +201,7 @@ fn augment_references_with_imports( let import_scope = ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); let path = ref_module - .find_use_path_prefixed( + .find_use_path( ctx.sema.db, ModuleDef::Module(*target_module), ctx.config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs index c1a3f9302650e..bdcefe0b4fdaf 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs @@ -90,7 +90,7 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option) -> Op FamousDefs(&ctx.sema, module.krate()).core_ops_ControlFlow(); if let Some(control_flow_enum) = control_flow_enum { - let mod_path = module.find_use_path_prefixed( + let mod_path = module.find_use_path( ctx.sema.db, ModuleDef::from(control_flow_enum), ctx.config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs index 81a639e0b9f3d..24bda139b2cd0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs @@ -386,7 +386,7 @@ fn process_references( let segment = builder.make_mut(segment); let scope_node = builder.make_syntax_mut(scope_node); if !visited_modules.contains(&module) { - let mod_path = module.find_use_path_prefixed( + let mod_path = module.find_use_path( ctx.sema.db, *enum_module_def, ctx.config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs index 473c699b595c6..54c320a39b1a8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs @@ -58,7 +58,7 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; - let trait_path = module.find_use_path( + let trait_path = module.find_path( ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_no_std, @@ -103,7 +103,7 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<() let module = ctx.sema.to_def(&strukt)?.module(ctx.db()); let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?; - let trait_path = module.find_use_path( + let trait_path = module.find_path( ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs index 22c75cd5eefc9..50342b0284e3e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs @@ -58,7 +58,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?)); - let type_path = current_module.find_use_path( + let type_path = current_module.find_path( ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?, ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs index ff65aac82e070..196b33e0f6754 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs @@ -44,7 +44,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> let current_module = ctx.sema.scope(call.syntax())?.module(); let target_module_def = ModuleDef::from(resolved_call); let item_in_ns = ItemInNs::from(target_module_def); - let receiver_path = current_module.find_use_path( + let receiver_path = current_module.find_path( ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?, ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index 3420d906dea5a..8cc7c883f4ce3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -83,7 +83,7 @@ pub(crate) fn replace_derive_with_manual_impl( }) .flat_map(|trait_| { current_module - .find_use_path( + .find_path( ctx.sema.db, hir::ModuleDef::Trait(trait_), ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs index ba1c25fa5a749..cb9de32d9cd04 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs @@ -63,7 +63,7 @@ pub(crate) fn replace_qualified_name_with_use( ); let path_to_qualifier = starts_with_name_ref .then(|| { - ctx.sema.scope(path.syntax())?.module().find_use_path_prefixed( + ctx.sema.scope(path.syntax())?.module().find_use_path( ctx.sema.db, module, ctx.config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index 1ea7220960d25..69b0289fc1dd0 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -633,7 +633,7 @@ fn enum_variants_with_paths( } for variant in variants { - if let Some(path) = ctx.module.find_use_path( + if let Some(path) = ctx.module.find_path( ctx.db, hir::ModuleDef::from(variant), ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 1e31d65fddfe6..f350c2743c7cb 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -171,7 +171,7 @@ pub(crate) fn complete_expr_path( hir::Adt::Struct(strukt) => { let path = ctx .module - .find_use_path( + .find_path( ctx.db, hir::ModuleDef::from(strukt), ctx.config.prefer_no_std, @@ -194,7 +194,7 @@ pub(crate) fn complete_expr_path( hir::Adt::Union(un) => { let path = ctx .module - .find_use_path( + .find_path( ctx.db, hir::ModuleDef::from(un), ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index c6e243b31a791..c14da34874b3a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -63,7 +63,7 @@ pub(crate) fn complete_postfix( if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() { if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) { if let Some(drop_fn) = ctx.famous_defs().core_mem_drop() { - if let Some(path) = ctx.module.find_use_path( + if let Some(path) = ctx.module.find_path( ctx.db, ItemInNs::Values(drop_fn.into()), ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index d89cfc8b6cb83..4165dd48af460 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -260,7 +260,7 @@ pub fn resolve_completion_edits( ); let import = items_with_name .filter_map(|candidate| { - current_module.find_use_path_prefixed( + current_module.find_use_path( db, candidate, config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 7fa31e2757db3..d7b27f8b3b3ae 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -333,7 +333,7 @@ pub(crate) fn render_expr( }); for trait_ in expr.traits_used(ctx.db) { let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_)); - let Some(path) = ctx.module.find_use_path( + let Some(path) = ctx.module.find_path( ctx.db, trait_item, ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs index 7d710f1e1308c..37bb6cfef0a99 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs @@ -174,7 +174,7 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option def.into(), _ => return None, }; - let path = ctx.module.find_use_path_prefixed( + let path = ctx.module.find_use_path( ctx.db, item, ctx.config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 766bfcf4d0947..5e33b08e4a41c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -637,17 +637,13 @@ fn get_mod_path( prefer_no_std: bool, prefer_prelude: bool, ) -> Option { - if let Some(prefix_kind) = prefixed { - module_with_candidate.find_use_path_prefixed( - db, - item_to_search, - prefix_kind, - prefer_no_std, - prefer_prelude, - ) - } else { - module_with_candidate.find_use_path(db, item_to_search, prefer_no_std, prefer_prelude) - } + module_with_candidate.find_use_path( + db, + item_to_search, + prefixed.unwrap_or(PrefixKind::Plain), + prefer_no_std, + prefer_prelude, + ) } impl ImportCandidate { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs index 7e1811b4cacb6..6f4f97e0b86cf 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs @@ -308,7 +308,7 @@ impl Ctx<'_> { parent.segment()?.name_ref()?, ) .and_then(|trait_ref| { - let found_path = self.target_module.find_use_path( + let found_path = self.target_module.find_path( self.source_scope.db.upcast(), hir::ModuleDef::Trait(trait_ref), false, @@ -347,7 +347,7 @@ impl Ctx<'_> { } } - let found_path = self.target_module.find_use_path( + let found_path = self.target_module.find_path( self.source_scope.db.upcast(), def, false, @@ -385,7 +385,7 @@ impl Ctx<'_> { if let Some(adt) = ty.as_adt() { if let ast::Type::PathType(path_ty) = &ast_ty { - let found_path = self.target_module.find_use_path( + let found_path = self.target_module.find_path( self.source_scope.db.upcast(), ModuleDef::from(adt), false, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs index b3dde977b1c4f..71958bc8660f4 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs @@ -144,7 +144,7 @@ pub(crate) fn json_in_items( let current_module = semantics_scope.module(); if !scope_has("Serialize") { if let Some(PathResolution::Def(it)) = serialize_resolved { - if let Some(it) = current_module.find_use_path_prefixed( + if let Some(it) = current_module.find_use_path( sema.db, it, config.insert_use.prefix_kind, @@ -157,7 +157,7 @@ pub(crate) fn json_in_items( } if !scope_has("Deserialize") { if let Some(PathResolution::Def(it)) = deserialize_resolved { - if let Some(it) = current_module.find_use_path_prefixed( + if let Some(it) = current_module.find_use_path( sema.db, it, config.insert_use.prefix_kind, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index f92ba576d3ab5..ed9094f1f3613 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -122,7 +122,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option Option { let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?)); - let type_path = current_module?.find_use_path( + let type_path = current_module?.find_path( ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?, ctx.config.prefer_no_std, diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index cfda1c692aea8..99df3f2563dfd 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -664,7 +664,7 @@ impl Match { for (path, resolved_path) in &template.resolved_paths { if let hir::PathResolution::Def(module_def) = resolved_path.resolution { let mod_path = - module.find_use_path(sema.db, module_def, false, true).ok_or_else(|| { + module.find_path(sema.db, module_def, false, true).ok_or_else(|| { match_error!("Failed to render template path `{}` at match location") })?; self.rendered_template_paths.insert(path.clone(), mod_path);