Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 0ed9a5f

Browse files
committed
Specialize find_path local search
1 parent 66a4e55 commit 0ed9a5f

File tree

1 file changed

+45
-28
lines changed

1 file changed

+45
-28
lines changed

src/tools/rust-analyzer/crates/hir-def/src/find_path.rs

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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

251255
fn 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

Comments
 (0)