@@ -116,7 +116,7 @@ fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Opt
116
116
// - if the item is a module, jump straight to module search
117
117
if let ItemInNs :: Types ( ModuleDefId :: ModuleId ( module_id) ) = item {
118
118
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)
120
120
. map ( |choice| choice. path ) ;
121
121
}
122
122
@@ -161,10 +161,11 @@ fn find_path_for_module(
161
161
ctx : & FindPathCtx < ' _ > ,
162
162
visited_modules : & mut FxHashSet < ModuleId > ,
163
163
module_id : ModuleId ,
164
+ maybe_extern : bool ,
164
165
max_len : usize ,
165
166
) -> Option < Choice > {
166
167
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 ( ) {
168
169
// - if the item is the crate root, return `crate`
169
170
return Some ( Choice {
170
171
path : ModPath :: from_segments ( PathKind :: Crate , None ) ,
@@ -240,12 +241,15 @@ fn find_path_for_module(
240
241
}
241
242
242
243
// - 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 ) {
246
246
return Some ( choice) ;
247
247
}
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
+ }
249
253
}
250
254
251
255
fn find_in_scope (
@@ -347,31 +351,13 @@ fn calculate_best_path(
347
351
}
348
352
ctx. fuel . set ( fuel - 1 ) ;
349
353
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 ) {
353
355
// Item was defined in the same crate that wants to import it. It cannot be found in any
354
356
// 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)
374
358
} else {
359
+ let mut best_choice = None :: < Choice > ;
360
+ let db = ctx. db ;
375
361
// Item was defined in some upstream crate. This means that it must be exported from one,
376
362
// too (unless we can't name it at all). It could *also* be (re)exported by the same crate
377
363
// that wants to import it here, but we always prefer to use the external path here.
@@ -394,6 +380,7 @@ fn calculate_best_path(
394
380
ctx,
395
381
visited_modules,
396
382
info. container ,
383
+ true ,
397
384
best_choice. as_ref ( ) . map_or ( max_len, |it| it. path_len ) - 1 ,
398
385
) ;
399
386
let Some ( mut choice) = choice else {
@@ -453,7 +440,37 @@ fn calculate_best_path(
453
440
. iter ( )
454
441
. filter ( |it| !ctx. is_std_item || !it. is_sysroot ( ) )
455
442
. for_each ( |dep| _ = process_dep ( dep. crate_id , 0 ) ) ;
443
+ best_choice
456
444
}
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
+ } ) ;
457
474
best_choice
458
475
}
459
476
0 commit comments