From 3a4e99115d1f64243eb12b5c937b4ad90b4ad014 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 21 Mar 2021 23:45:00 +0200 Subject: Do not revisit recursively imported modules --- crates/hir_def/src/find_path.rs | 54 +++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index de08e2737..b4362a5c4 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs @@ -18,7 +18,8 @@ use crate::{ /// *from where* you're referring to the item, hence the `from` parameter. pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option { let _p = profile::span("find_path"); - find_path_inner(db, item, from, MAX_PATH_LEN, None) + let mut visited_modules = FxHashSet::default(); + find_path_inner(db, item, from, MAX_PATH_LEN, None, &mut visited_modules) } pub fn find_path_prefixed( @@ -28,7 +29,8 @@ pub fn find_path_prefixed( prefix_kind: PrefixKind, ) -> Option { let _p = profile::span("find_path_prefixed"); - find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind)) + let mut visited_modules = FxHashSet::default(); + find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind), &mut visited_modules) } const MAX_PATH_LEN: usize = 15; @@ -97,6 +99,7 @@ fn find_path_inner( from: ModuleId, max_len: usize, mut prefixed: Option, + visited_modules: &mut FxHashSet, ) -> Option { if max_len == 0 { return None; @@ -176,15 +179,17 @@ fn find_path_inner( if item.krate(db) == Some(from.krate) { // Item was defined in the same crate that wants to import it. It cannot be found in any // dependency in this case. - - let local_imports = find_local_import_locations(db, item, from); - for (module_id, name) in local_imports { + for (module_id, name) in find_local_import_locations(db, item, from) { + if !visited_modules.insert(module_id) { + continue; + } if let Some(mut path) = find_path_inner( db, ItemInNs::Types(ModuleDefId::ModuleId(module_id)), from, best_path_len - 1, prefixed, + visited_modules, ) { path.push_segment(name); @@ -213,6 +218,7 @@ fn find_path_inner( from, best_path_len - 1, prefixed, + visited_modules, )?; cov_mark::hit!(partially_imported); path.push_segment(info.path.segments.last().unwrap().clone()); @@ -391,8 +397,15 @@ mod tests { .take_types() .unwrap(); - let found_path = - find_path_inner(&db, ItemInNs::Types(resolved), module, MAX_PATH_LEN, prefix_kind); + let mut visited_modules = FxHashSet::default(); + let found_path = find_path_inner( + &db, + ItemInNs::Types(resolved), + module, + MAX_PATH_LEN, + prefix_kind, + &mut visited_modules, + ); assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind); } @@ -878,4 +891,31 @@ mod tests { "self::module::CompleteMe", ) } + + #[test] + fn recursive_pub_mod_reexport() { + check_found_path( + r#" +fn main() { + let _ = 22_i32.as_name$0(); +} + +pub mod name { + pub trait AsName { + fn as_name(&self) -> String; + } + impl AsName for i32 { + fn as_name(&self) -> String { + format!("Name: {}", self) + } + } + pub use crate::name; +} +"#, + "name::AsName", + "name::AsName", + "crate::name::AsName", + "self::name::AsName", + ); + } } -- cgit v1.2.3