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(
2825from : ModuleId ,
2926prefix_kind : PrefixKind ,
3027ignore_local_imports : bool ,
31- prefer_no_std : bool ,
32- prefer_prelude : bool ,
28+ cfg : ImportPathConfig ,
3329) ->Option < ModPath > {
3430let _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 > {
8975db : & ' db dyn DefDatabase ,
9076prefix : PrefixKind ,
91- prefer_no_std : bool ,
92- prefer_prelude : bool ,
77+ cfg : ImportPathConfig ,
9378ignore_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
9984if 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
10388let def_map = from. def_map ( ctx. db ) ;
@@ -107,7 +92,11 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
10792let mut visited_modules =FxHashSet :: default ( ) ;
10893return find_path_for_module (
10994FindPathCtx {
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
133122let scope_name =find_in_scope ( ctx. db , & def_map, from, item, ctx. ignore_local_imports ) ;
134123if 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
161150calculate_best_path (
162151FindPathCtx {
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 {
214207PathKind :: 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}
219212let prefix =if module_id. is_within_block ( ) { PrefixKind :: Plain } else { ctx. prefix } ;
@@ -231,7 +224,10 @@ fn find_path_for_module(
231224) ;
232225if 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
307303if 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 {
310306None
311307}
@@ -381,9 +377,7 @@ fn calculate_best_path(
381377 path. 0 . push_segment ( name) ;
382378
383379let 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 ) ,
387381None => path,
388382} ;
389383 best_path_len = new_path. 0 . len ( ) ;
@@ -425,12 +419,7 @@ fn calculate_best_path(
425419) ;
426420
427421let 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 ) ,
434423None => path_with_stab,
435424} ;
436425update_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 ) {
452440match ( old_stability, new_stability) {
453441( Stable , Unstable ) =>return old_path,
@@ -461,7 +449,7 @@ fn select_best_path(
461449let ( old_path, _) =& old;
462450let new_has_prelude = new_path. segments ( ) . iter ( ) . any ( |seg| seg ==& known:: prelude) ;
463451let 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
483471match ( 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 {
486474false => |name : & Name |match name{
487475 nameif name ==& known:: core =>0 ,
488476 nameif name ==& known:: alloc =>1 ,
@@ -647,10 +635,9 @@ mod tests {
647635{
648636let found_path =find_path_inner (
649637FindPathCtx {
650- prefer_no_std : false ,
651638db : & db,
652639 prefix,
653- prefer_prelude,
640+ cfg : ImportPathConfig { prefer_no_std : false , prefer_prelude} ,
654641 ignore_local_imports,
655642} ,
656643 resolved,