11//! An algorithm to find a path to refer to a certain item.
22
3- use std::{
4- cmp::Ordering,
5- iter::{self, once},
6- };
3+ use std::{cmp::Ordering, iter};
74
85use hir_expand::{
96 name::{known, AsName, Name},
@@ -17,7 +14,7 @@ use crate::{
1714 nameres::DefMap,
1815 path::{ModPath, PathKind},
1916 visibility::{Visibility, VisibilityExplicitness},
20- ModuleDefId, ModuleId,
17+ ImportPathConfig, ModuleDefId, ModuleId,
2118};
2219
2320/// Find a path that can be used to refer to a certain item. This can depend on
@@ -28,21 +25,10 @@ pub fn find_path(
2825 from: ModuleId,
2926 prefix_kind: PrefixKind,
3027 ignore_local_imports: bool,
31- prefer_no_std: bool,
32- prefer_prelude: bool,
28+ cfg: ImportPathConfig,
3329) -> Option<ModPath> {
3430 let _p = tracing::span!(tracing::Level::INFO, "find_path").entered();
35- find_path_inner(
36- FindPathCtx {
37- db,
38- prefix: prefix_kind,
39- prefer_no_std,
40- prefer_prelude,
41- ignore_local_imports,
42- },
43- item,
44- from,
45- )
31+ find_path_inner(FindPathCtx { db, prefix: prefix_kind, cfg, ignore_local_imports }, item, from)
4632}
4733
4834#[derive(Copy, Clone, Debug)]
@@ -88,16 +74,15 @@ impl PrefixKind {
8874struct FindPathCtx<'db> {
8975 db: &'db dyn DefDatabase,
9076 prefix: PrefixKind,
91- prefer_no_std: bool,
92- prefer_prelude: bool,
77+ cfg: ImportPathConfig,
9378 ignore_local_imports: bool,
9479}
9580
9681/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
9782fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
9883 // - if the item is a builtin, it's in scope
9984 if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item {
100- return Some(ModPath::from_segments(PathKind::Plain, once(builtin.as_name())));
85+ return Some(ModPath::from_segments(PathKind::Plain, iter:: once(builtin.as_name())));
10186 }
10287
10388 let def_map = from.def_map(ctx.db);
@@ -107,7 +92,11 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
10792 let mut visited_modules = FxHashSet::default();
10893 return find_path_for_module(
10994 FindPathCtx {
110- prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate),
95+ cfg: ImportPathConfig {
96+ prefer_no_std: ctx.cfg.prefer_no_std
97+ || ctx.db.crate_supports_no_std(crate_root.krate),
98+ ..ctx.cfg
99+ },
111100 ..ctx
112101 },
113102 &def_map,
@@ -132,7 +121,7 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
132121 // - if the item is already in scope, return the name under which it is
133122 let scope_name = find_in_scope(ctx.db, &def_map, from, item, ctx.ignore_local_imports);
134123 if let Some(scope_name) = scope_name {
135- return Some(ModPath::from_segments(prefix.path_kind(), Some (scope_name)));
124+ return Some(ModPath::from_segments(prefix.path_kind(), iter::once (scope_name)));
136125 }
137126 }
138127
@@ -160,7 +149,11 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
160149
161150 calculate_best_path(
162151 FindPathCtx {
163- prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate),
152+ cfg: ImportPathConfig {
153+ prefer_no_std: ctx.cfg.prefer_no_std
154+ || ctx.db.crate_supports_no_std(crate_root.krate),
155+ ..ctx.cfg
156+ },
164157 ..ctx
165158 },
166159 &def_map,
@@ -213,7 +206,7 @@ fn find_path_for_module(
213206 } else {
214207 PathKind::Plain
215208 };
216- return Some((ModPath::from_segments(kind, once(name.clone())), Stable));
209+ return Some((ModPath::from_segments(kind, iter:: once(name.clone())), Stable));
217210 }
218211 }
219212 let prefix = if module_id.is_within_block() { PrefixKind::Plain } else { ctx.prefix };
@@ -231,7 +224,10 @@ fn find_path_for_module(
231224 );
232225 if let Some(scope_name) = scope_name {
233226 // - if the item is already in scope, return the name under which it is
234- return Some((ModPath::from_segments(prefix.path_kind(), once(scope_name)), Stable));
227+ return Some((
228+ ModPath::from_segments(prefix.path_kind(), iter::once(scope_name)),
229+ Stable,
230+ ));
235231 }
236232 }
237233
@@ -305,7 +301,7 @@ fn find_in_prelude(
305301 });
306302
307303 if found_and_same_def.unwrap_or(true) {
308- Some(ModPath::from_segments(PathKind::Plain, once(name.clone())))
304+ Some(ModPath::from_segments(PathKind::Plain, iter:: once(name.clone())))
309305 } else {
310306 None
311307 }
@@ -381,9 +377,7 @@ fn calculate_best_path(
381377 path.0.push_segment(name);
382378
383379 let new_path = match best_path.take() {
384- Some(best_path) => {
385- select_best_path(best_path, path, ctx.prefer_no_std, ctx.prefer_prelude)
386- }
380+ Some(best_path) => select_best_path(best_path, path, ctx.cfg),
387381 None => path,
388382 };
389383 best_path_len = new_path.0.len();
@@ -425,12 +419,7 @@ fn calculate_best_path(
425419 );
426420
427421 let new_path_with_stab = match best_path.take() {
428- Some(best_path) => select_best_path(
429- best_path,
430- path_with_stab,
431- ctx.prefer_no_std,
432- ctx.prefer_prelude,
433- ),
422+ Some(best_path) => select_best_path(best_path, path_with_stab, ctx.cfg),
434423 None => path_with_stab,
435424 };
436425 update_best_path(&mut best_path, new_path_with_stab);
@@ -446,8 +435,7 @@ fn calculate_best_path(
446435fn select_best_path(
447436 old_path @ (_, old_stability): (ModPath, Stability),
448437 new_path @ (_, new_stability): (ModPath, Stability),
449- prefer_no_std: bool,
450- prefer_prelude: bool,
438+ cfg: ImportPathConfig,
451439) -> (ModPath, Stability) {
452440 match (old_stability, new_stability) {
453441 (Stable, Unstable) => return old_path,
@@ -461,7 +449,7 @@ fn select_best_path(
461449 let (old_path, _) = &old;
462450 let new_has_prelude = new_path.segments().iter().any(|seg| seg == &known::prelude);
463451 let old_has_prelude = old_path.segments().iter().any(|seg| seg == &known::prelude);
464- match (new_has_prelude, old_has_prelude, prefer_prelude) {
452+ match (new_has_prelude, old_has_prelude, cfg. prefer_prelude) {
465453 (true, false, true) | (false, true, false) => new,
466454 (true, false, false) | (false, true, true) => old,
467455 // no prelude difference in the paths, so pick the shorter one
@@ -482,7 +470,7 @@ fn select_best_path(
482470
483471 match (old_path.0.segments().first(), new_path.0.segments().first()) {
484472 (Some(old), Some(new)) if STD_CRATES.contains(old) && STD_CRATES.contains(new) => {
485- let rank = match prefer_no_std {
473+ let rank = match cfg. prefer_no_std {
486474 false => |name: &Name| match name {
487475 name if name == &known::core => 0,
488476 name if name == &known::alloc => 1,
@@ -647,10 +635,9 @@ mod tests {
647635 {
648636 let found_path = find_path_inner(
649637 FindPathCtx {
650- prefer_no_std: false,
651638 db: &db,
652639 prefix,
653- prefer_prelude,
640+ cfg: ImportPathConfig { prefer_no_std: false, prefer_prelude } ,
654641 ignore_local_imports,
655642 },
656643 resolved,
0 commit comments