1
1
//! An algorithm to find a path to refer to a certain item.
2
2
3
- use std:: {
4
- cmp:: Ordering ,
5
- iter:: { self , once} ,
6
- } ;
3
+ use std:: { cmp:: Ordering , iter} ;
7
4
8
5
use hir_expand:: {
9
6
name:: { known, AsName , Name } ,
@@ -17,7 +14,7 @@ use crate::{
17
14
nameres:: DefMap ,
18
15
path:: { ModPath , PathKind } ,
19
16
visibility:: { Visibility , VisibilityExplicitness } ,
20
- ModuleDefId , ModuleId ,
17
+ ImportPathConfig , ModuleDefId , ModuleId ,
21
18
} ;
22
19
23
20
/// 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(
28
25
from : ModuleId ,
29
26
prefix_kind : PrefixKind ,
30
27
ignore_local_imports : bool ,
31
- prefer_no_std : bool ,
32
- prefer_prelude : bool ,
28
+ cfg : ImportPathConfig ,
33
29
) -> Option < ModPath > {
34
30
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)
46
32
}
47
33
48
34
#[ derive( Copy , Clone , Debug ) ]
@@ -88,16 +74,15 @@ impl PrefixKind {
88
74
struct FindPathCtx < ' db > {
89
75
db : & ' db dyn DefDatabase ,
90
76
prefix : PrefixKind ,
91
- prefer_no_std : bool ,
92
- prefer_prelude : bool ,
77
+ cfg : ImportPathConfig ,
93
78
ignore_local_imports : bool ,
94
79
}
95
80
96
81
/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
97
82
fn find_path_inner ( ctx : FindPathCtx < ' _ > , item : ItemInNs , from : ModuleId ) -> Option < ModPath > {
98
83
// - if the item is a builtin, it's in scope
99
84
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 ( ) ) ) ) ;
101
86
}
102
87
103
88
let def_map = from. def_map ( ctx. db ) ;
@@ -107,7 +92,11 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
107
92
let mut visited_modules = FxHashSet :: default ( ) ;
108
93
return find_path_for_module (
109
94
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
+ } ,
111
100
..ctx
112
101
} ,
113
102
& def_map,
@@ -132,7 +121,7 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
132
121
// - if the item is already in scope, return the name under which it is
133
122
let scope_name = find_in_scope ( ctx. db , & def_map, from, item, ctx. ignore_local_imports ) ;
134
123
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) ) ) ;
136
125
}
137
126
}
138
127
@@ -160,7 +149,11 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
160
149
161
150
calculate_best_path (
162
151
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
+ } ,
164
157
..ctx
165
158
} ,
166
159
& def_map,
@@ -213,7 +206,7 @@ fn find_path_for_module(
213
206
} else {
214
207
PathKind :: Plain
215
208
} ;
216
- return Some ( ( ModPath :: from_segments ( kind, once ( name. clone ( ) ) ) , Stable ) ) ;
209
+ return Some ( ( ModPath :: from_segments ( kind, iter :: once ( name. clone ( ) ) ) , Stable ) ) ;
217
210
}
218
211
}
219
212
let prefix = if module_id. is_within_block ( ) { PrefixKind :: Plain } else { ctx. prefix } ;
@@ -231,7 +224,10 @@ fn find_path_for_module(
231
224
) ;
232
225
if let Some ( scope_name) = scope_name {
233
226
// - 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
+ ) ) ;
235
231
}
236
232
}
237
233
@@ -305,7 +301,7 @@ fn find_in_prelude(
305
301
} ) ;
306
302
307
303
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 ( ) ) ) )
309
305
} else {
310
306
None
311
307
}
@@ -381,9 +377,7 @@ fn calculate_best_path(
381
377
path. 0 . push_segment ( name) ;
382
378
383
379
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 ) ,
387
381
None => path,
388
382
} ;
389
383
best_path_len = new_path. 0 . len ( ) ;
@@ -425,12 +419,7 @@ fn calculate_best_path(
425
419
) ;
426
420
427
421
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 ) ,
434
423
None => path_with_stab,
435
424
} ;
436
425
update_best_path ( & mut best_path, new_path_with_stab) ;
@@ -446,8 +435,7 @@ fn calculate_best_path(
446
435
fn select_best_path (
447
436
old_path @ ( _, old_stability) : ( ModPath , Stability ) ,
448
437
new_path @ ( _, new_stability) : ( ModPath , Stability ) ,
449
- prefer_no_std : bool ,
450
- prefer_prelude : bool ,
438
+ cfg : ImportPathConfig ,
451
439
) -> ( ModPath , Stability ) {
452
440
match ( old_stability, new_stability) {
453
441
( Stable , Unstable ) => return old_path,
@@ -461,7 +449,7 @@ fn select_best_path(
461
449
let ( old_path, _) = & old;
462
450
let new_has_prelude = new_path. segments ( ) . iter ( ) . any ( |seg| seg == & known:: prelude) ;
463
451
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 ) {
465
453
( true , false , true ) | ( false , true , false ) => new,
466
454
( true , false , false ) | ( false , true , true ) => old,
467
455
// no prelude difference in the paths, so pick the shorter one
@@ -482,7 +470,7 @@ fn select_best_path(
482
470
483
471
match ( old_path. 0 . segments ( ) . first ( ) , new_path. 0 . segments ( ) . first ( ) ) {
484
472
( 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 {
486
474
false => |name : & Name | match name {
487
475
name if name == & known:: core => 0 ,
488
476
name if name == & known:: alloc => 1 ,
@@ -647,10 +635,9 @@ mod tests {
647
635
{
648
636
let found_path = find_path_inner (
649
637
FindPathCtx {
650
- prefer_no_std : false ,
651
638
db : & db,
652
639
prefix,
653
- prefer_prelude,
640
+ cfg : ImportPathConfig { prefer_no_std : false , prefer_prelude } ,
654
641
ignore_local_imports,
655
642
} ,
656
643
resolved,
0 commit comments