@@ -116,7 +116,7 @@ fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Opt
116116 // - if the item is a module, jump straight to module search
117117 if let ItemInNs :: Types ( ModuleDefId :: ModuleId ( module_id) ) = item {
118118 let mut visited_modules = FxHashSet :: default ( ) ;
119- return find_path_for_module ( ctx, & mut visited_modules, module_id, max_len)
119+ return find_path_for_module ( ctx, & mut visited_modules, module_id, true , max_len)
120120 . map ( |choice| choice. path ) ;
121121 }
122122
@@ -161,10 +161,11 @@ fn find_path_for_module(
161161 ctx : & FindPathCtx < ' _ > ,
162162 visited_modules : & mut FxHashSet < ModuleId > ,
163163 module_id : ModuleId ,
164+ maybe_extern : bool ,
164165 max_len : usize ,
165166) -> Option < Choice > {
166167 if let Some ( crate_root) = module_id. as_crate_root ( ) {
167- if crate_root == ctx. from . derive_crate_root ( ) {
168+ if !maybe_extern || crate_root == ctx. from . derive_crate_root ( ) {
168169 // - if the item is the crate root, return `crate`
169170 return Some ( Choice {
170171 path : ModPath :: from_segments ( PathKind :: Crate , None ) ,
@@ -240,12 +241,15 @@ fn find_path_for_module(
240241 }
241242
242243 // - if the module is in the prelude, return it by that path
243- if let Some ( choice) =
244- find_in_prelude ( ctx. db , ctx. from_def_map , ItemInNs :: Types ( module_id. into ( ) ) , ctx. from )
245- {
244+ let item = ItemInNs :: Types ( module_id. into ( ) ) ;
245+ if let Some ( choice) = find_in_prelude ( ctx. db , ctx. from_def_map , item, ctx. from ) {
246246 return Some ( choice) ;
247247 }
248- calculate_best_path ( ctx, visited_modules, ItemInNs :: Types ( module_id. into ( ) ) , max_len)
248+ if maybe_extern {
249+ calculate_best_path ( ctx, visited_modules, item, max_len)
250+ } else {
251+ calculate_best_path_local ( ctx, visited_modules, item, max_len)
252+ }
249253}
250254
251255fn find_in_scope (
@@ -347,31 +351,13 @@ fn calculate_best_path(
347351 }
348352 ctx. fuel . set ( fuel - 1 ) ;
349353
350- let mut best_choice = None :: < Choice > ;
351- let db = ctx. db ;
352- if item. krate ( db) == Some ( ctx. from . krate ) {
354+ if item. krate ( ctx. db ) == Some ( ctx. from . krate ) {
353355 // Item was defined in the same crate that wants to import it. It cannot be found in any
354356 // dependency in this case.
355- // FIXME: cache the `find_local_import_locations` output?
356- find_local_import_locations ( db, item, ctx. from , ctx. from_def_map , |name, module_id| {
357- if !visited_modules. insert ( module_id) {
358- return ;
359- }
360- // we are looking for paths of length up to best_path_len, any longer will make it be
361- // less optimal. The -1 is due to us pushing name onto it afterwards.
362- if let Some ( path) = find_path_for_module (
363- ctx,
364- visited_modules,
365- module_id,
366- best_choice. as_ref ( ) . map_or ( max_len, |it| it. path_len ) - 1 ,
367- ) {
368- best_choice = Some ( match best_choice. take ( ) {
369- Some ( best_choice) => best_choice. select ( path, name. clone ( ) ) ,
370- None => path. push ( ctx. cfg . prefer_prelude , name. clone ( ) ) ,
371- } ) ;
372- }
373- } )
357+ calculate_best_path_local ( ctx, visited_modules, item, max_len)
374358 } else {
359+ let mut best_choice = None :: < Choice > ;
360+ let db = ctx. db ;
375361 // Item was defined in some upstream crate. This means that it must be exported from one,
376362 // too (unless we can't name it at all). It could *also* be (re)exported by the same crate
377363 // that wants to import it here, but we always prefer to use the external path here.
@@ -394,6 +380,7 @@ fn calculate_best_path(
394380 ctx,
395381 visited_modules,
396382 info. container ,
383+ true ,
397384 best_choice. as_ref ( ) . map_or ( max_len, |it| it. path_len ) - 1 ,
398385 ) ;
399386 let Some ( mut choice) = choice else {
@@ -453,7 +440,37 @@ fn calculate_best_path(
453440 . iter ( )
454441 . filter ( |it| !ctx. is_std_item || !it. is_sysroot ( ) )
455442 . for_each ( |dep| _ = process_dep ( dep. crate_id , 0 ) ) ;
443+ best_choice
456444 }
445+ }
446+
447+ fn calculate_best_path_local (
448+ ctx : & FindPathCtx < ' _ > ,
449+ visited_modules : & mut FxHashSet < ModuleId > ,
450+ item : ItemInNs ,
451+ max_len : usize ,
452+ ) -> Option < Choice > {
453+ let mut best_choice = None :: < Choice > ;
454+ // FIXME: cache the `find_local_import_locations` output?
455+ find_local_import_locations ( ctx. db , item, ctx. from , ctx. from_def_map , |name, module_id| {
456+ if !visited_modules. insert ( module_id) {
457+ return ;
458+ }
459+ // we are looking for paths of length up to best_path_len, any longer will make it be
460+ // less optimal. The -1 is due to us pushing name onto it afterwards.
461+ if let Some ( path) = find_path_for_module (
462+ ctx,
463+ visited_modules,
464+ module_id,
465+ false ,
466+ best_choice. as_ref ( ) . map_or ( max_len, |it| it. path_len ) - 1 ,
467+ ) {
468+ best_choice = Some ( match best_choice. take ( ) {
469+ Some ( best_choice) => best_choice. select ( path, name. clone ( ) ) ,
470+ None => path. push ( ctx. cfg . prefer_prelude , name. clone ( ) ) ,
471+ } ) ;
472+ }
473+ } ) ;
457474 best_choice
458475}
459476
0 commit comments