@@ -37,6 +37,20 @@ pub fn find_path_prefixed(
37
37
find_path_inner ( db, item, from, Some ( prefix_kind) , prefer_no_std)
38
38
}
39
39
40
+ #[ derive( Copy , Clone , Debug ) ]
41
+ enum Stability {
42
+ Unstable ,
43
+ Stable ,
44
+ }
45
+ use Stability :: * ;
46
+
47
+ fn zip_stability ( a : Stability , b : Stability ) -> Stability {
48
+ match ( a, b) {
49
+ ( Stable , Stable ) => Stable ,
50
+ _ => Unstable ,
51
+ }
52
+ }
53
+
40
54
const MAX_PATH_LEN : usize = 15 ;
41
55
42
56
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
@@ -95,7 +109,8 @@ fn find_path_inner(
95
109
MAX_PATH_LEN ,
96
110
prefixed,
97
111
prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
98
- ) ;
112
+ )
113
+ . map ( |( item, _) | item) ;
99
114
}
100
115
101
116
// - if the item is already in scope, return the name under which it is
@@ -143,6 +158,7 @@ fn find_path_inner(
143
158
prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
144
159
scope_name,
145
160
)
161
+ . map ( |( item, _) | item)
146
162
}
147
163
148
164
fn find_path_for_module (
@@ -155,7 +171,7 @@ fn find_path_for_module(
155
171
max_len : usize ,
156
172
prefixed : Option < PrefixKind > ,
157
173
prefer_no_std : bool ,
158
- ) -> Option < ModPath > {
174
+ ) -> Option < ( ModPath , Stability ) > {
159
175
if max_len == 0 {
160
176
return None ;
161
177
}
@@ -165,19 +181,19 @@ fn find_path_for_module(
165
181
let scope_name = find_in_scope ( db, def_map, from, ItemInNs :: Types ( module_id. into ( ) ) ) ;
166
182
if prefixed. is_none ( ) {
167
183
if let Some ( scope_name) = scope_name {
168
- return Some ( ModPath :: from_segments ( PathKind :: Plain , Some ( scope_name) ) ) ;
184
+ return Some ( ( ModPath :: from_segments ( PathKind :: Plain , Some ( scope_name) ) , Stable ) ) ;
169
185
}
170
186
}
171
187
172
188
// - if the item is the crate root, return `crate`
173
189
if module_id == crate_root {
174
- return Some ( ModPath :: from_segments ( PathKind :: Crate , None ) ) ;
190
+ return Some ( ( ModPath :: from_segments ( PathKind :: Crate , None ) , Stable ) ) ;
175
191
}
176
192
177
193
// - if relative paths are fine, check if we are searching for a parent
178
194
if prefixed. filter ( PrefixKind :: is_absolute) . is_none ( ) {
179
195
if let modpath @ Some ( _) = find_self_super ( def_map, module_id, from) {
180
- return modpath;
196
+ return modpath. zip ( Some ( Stable ) ) ;
181
197
}
182
198
}
183
199
@@ -201,14 +217,14 @@ fn find_path_for_module(
201
217
} else {
202
218
PathKind :: Plain
203
219
} ;
204
- return Some ( ModPath :: from_segments ( kind, Some ( name) ) ) ;
220
+ return Some ( ( ModPath :: from_segments ( kind, Some ( name) ) , Stable ) ) ;
205
221
}
206
222
}
207
223
208
224
if let value @ Some ( _) =
209
225
find_in_prelude ( db, & root_def_map, & def_map, ItemInNs :: Types ( module_id. into ( ) ) , from)
210
226
{
211
- return value;
227
+ return value. zip ( Some ( Stable ) ) ;
212
228
}
213
229
calculate_best_path (
214
230
db,
@@ -301,11 +317,19 @@ fn calculate_best_path(
301
317
mut prefixed : Option < PrefixKind > ,
302
318
prefer_no_std : bool ,
303
319
scope_name : Option < Name > ,
304
- ) -> Option < ModPath > {
320
+ ) -> Option < ( ModPath , Stability ) > {
305
321
if max_len <= 1 {
306
322
return None ;
307
323
}
308
324
let mut best_path = None ;
325
+ let update_best_path =
326
+ |best_path : & mut Option < _ > , new_path : ( ModPath , Stability ) | match best_path {
327
+ Some ( ( old_path, old_stability) ) => {
328
+ * old_path = new_path. 0 ;
329
+ * old_stability = zip_stability ( * old_stability, new_path. 1 ) ;
330
+ }
331
+ None => * best_path = Some ( new_path) ,
332
+ } ;
309
333
// Recursive case:
310
334
// - otherwise, look for modules containing (reexporting) it and import it from one of those
311
335
if item. krate ( db) == Some ( from. krate ) {
@@ -328,14 +352,14 @@ fn calculate_best_path(
328
352
prefixed,
329
353
prefer_no_std,
330
354
) {
331
- path. push_segment ( name) ;
355
+ path. 0 . push_segment ( name) ;
332
356
333
- let new_path = match best_path {
357
+ let new_path = match best_path. take ( ) {
334
358
Some ( best_path) => select_best_path ( best_path, path, prefer_no_std) ,
335
359
None => path,
336
360
} ;
337
- best_path_len = new_path. len ( ) ;
338
- best_path = Some ( new_path) ;
361
+ best_path_len = new_path. 0 . len ( ) ;
362
+ update_best_path ( & mut best_path, new_path) ;
339
363
}
340
364
}
341
365
} else {
@@ -354,7 +378,7 @@ fn calculate_best_path(
354
378
355
379
// Determine best path for containing module and append last segment from `info`.
356
380
// FIXME: we should guide this to look up the path locally, or from the same crate again?
357
- let mut path = find_path_for_module (
381
+ let ( mut path, path_stability ) = find_path_for_module (
358
382
db,
359
383
def_map,
360
384
visited_modules,
@@ -367,16 +391,19 @@ fn calculate_best_path(
367
391
) ?;
368
392
cov_mark:: hit!( partially_imported) ;
369
393
path. push_segment ( info. name . clone ( ) ) ;
370
- Some ( path)
394
+ Some ( (
395
+ path,
396
+ zip_stability ( path_stability, if info. is_unstable { Unstable } else { Stable } ) ,
397
+ ) )
371
398
} )
372
399
} ) ;
373
400
374
401
for path in extern_paths {
375
- let new_path = match best_path {
402
+ let new_path = match best_path. take ( ) {
376
403
Some ( best_path) => select_best_path ( best_path, path, prefer_no_std) ,
377
404
None => path,
378
405
} ;
379
- best_path = Some ( new_path) ;
406
+ update_best_path ( & mut best_path, new_path) ;
380
407
}
381
408
}
382
409
if let Some ( module) = item. module ( db) {
@@ -387,15 +414,24 @@ fn calculate_best_path(
387
414
}
388
415
match prefixed. map ( PrefixKind :: prefix) {
389
416
Some ( prefix) => best_path. or_else ( || {
390
- scope_name. map ( |scope_name| ModPath :: from_segments ( prefix, Some ( scope_name) ) )
417
+ scope_name. map ( |scope_name| ( ModPath :: from_segments ( prefix, Some ( scope_name) ) , Stable ) )
391
418
} ) ,
392
419
None => best_path,
393
420
}
394
421
}
395
422
396
- fn select_best_path ( old_path : ModPath , new_path : ModPath , prefer_no_std : bool ) -> ModPath {
423
+ fn select_best_path (
424
+ old_path : ( ModPath , Stability ) ,
425
+ new_path : ( ModPath , Stability ) ,
426
+ prefer_no_std : bool ,
427
+ ) -> ( ModPath , Stability ) {
428
+ match ( old_path. 1 , new_path. 1 ) {
429
+ ( Stable , Unstable ) => return old_path,
430
+ ( Unstable , Stable ) => return new_path,
431
+ _ => { }
432
+ }
397
433
const STD_CRATES : [ Name ; 3 ] = [ known:: std, known:: core, known:: alloc] ;
398
- match ( old_path. segments ( ) . first ( ) , new_path. segments ( ) . first ( ) ) {
434
+ match ( old_path. 0 . segments ( ) . first ( ) , new_path. 0 . segments ( ) . first ( ) ) {
399
435
( Some ( old) , Some ( new) ) if STD_CRATES . contains ( old) && STD_CRATES . contains ( new) => {
400
436
let rank = match prefer_no_std {
401
437
false => |name : & Name | match name {
@@ -416,7 +452,7 @@ fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -
416
452
match nrank. cmp ( & orank) {
417
453
Ordering :: Less => old_path,
418
454
Ordering :: Equal => {
419
- if new_path. len ( ) < old_path. len ( ) {
455
+ if new_path. 0 . len ( ) < old_path. 0 . len ( ) {
420
456
new_path
421
457
} else {
422
458
old_path
@@ -426,7 +462,7 @@ fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -
426
462
}
427
463
}
428
464
_ => {
429
- if new_path. len ( ) < old_path. len ( ) {
465
+ if new_path. 0 . len ( ) < old_path. 0 . len ( ) {
430
466
new_path
431
467
} else {
432
468
old_path
@@ -1360,4 +1396,29 @@ pub mod ops {
1360
1396
"std::ops::Deref" ,
1361
1397
) ;
1362
1398
}
1399
+
1400
+ #[ test]
1401
+ fn respect_unstable_modules ( ) {
1402
+ check_found_path (
1403
+ r#"
1404
+ //- /main.rs crate:main deps:std,core
1405
+ #![no_std]
1406
+ extern crate std;
1407
+ $0
1408
+ //- /longer.rs crate:std deps:core
1409
+ pub mod error {
1410
+ pub use core::error::Error;
1411
+ }
1412
+ //- /core.rs crate:core
1413
+ pub mod error {
1414
+ #![unstable(feature = "error_in_core", issue = "103765")]
1415
+ pub trait Error {}
1416
+ }
1417
+ "# ,
1418
+ "std::error::Error" ,
1419
+ "std::error::Error" ,
1420
+ "std::error::Error" ,
1421
+ "std::error::Error" ,
1422
+ ) ;
1423
+ }
1363
1424
}
0 commit comments