@@ -37,6 +37,20 @@ pub fn find_path_prefixed(
3737 find_path_inner ( db, item, from, Some ( prefix_kind) , prefer_no_std)
3838}
3939
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+
4054const MAX_PATH_LEN : usize = 15 ;
4155
4256#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
@@ -95,7 +109,8 @@ fn find_path_inner(
95109 MAX_PATH_LEN ,
96110 prefixed,
97111 prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
98- ) ;
112+ )
113+ . map ( |( item, _) | item) ;
99114 }
100115
101116 // - if the item is already in scope, return the name under which it is
@@ -143,6 +158,7 @@ fn find_path_inner(
143158 prefer_no_std || db. crate_supports_no_std ( crate_root. krate ) ,
144159 scope_name,
145160 )
161+ . map ( |( item, _) | item)
146162}
147163
148164fn find_path_for_module (
@@ -155,7 +171,7 @@ fn find_path_for_module(
155171 max_len : usize ,
156172 prefixed : Option < PrefixKind > ,
157173 prefer_no_std : bool ,
158- ) -> Option < ModPath > {
174+ ) -> Option < ( ModPath , Stability ) > {
159175 if max_len == 0 {
160176 return None ;
161177 }
@@ -165,19 +181,19 @@ fn find_path_for_module(
165181 let scope_name = find_in_scope ( db, def_map, from, ItemInNs :: Types ( module_id. into ( ) ) ) ;
166182 if prefixed. is_none ( ) {
167183 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 ) ) ;
169185 }
170186 }
171187
172188 // - if the item is the crate root, return `crate`
173189 if module_id == crate_root {
174- return Some ( ModPath :: from_segments ( PathKind :: Crate , None ) ) ;
190+ return Some ( ( ModPath :: from_segments ( PathKind :: Crate , None ) , Stable ) ) ;
175191 }
176192
177193 // - if relative paths are fine, check if we are searching for a parent
178194 if prefixed. filter ( PrefixKind :: is_absolute) . is_none ( ) {
179195 if let modpath @ Some ( _) = find_self_super ( def_map, module_id, from) {
180- return modpath;
196+ return modpath. zip ( Some ( Stable ) ) ;
181197 }
182198 }
183199
@@ -201,14 +217,14 @@ fn find_path_for_module(
201217 } else {
202218 PathKind :: Plain
203219 } ;
204- return Some ( ModPath :: from_segments ( kind, Some ( name) ) ) ;
220+ return Some ( ( ModPath :: from_segments ( kind, Some ( name) ) , Stable ) ) ;
205221 }
206222 }
207223
208224 if let value @ Some ( _) =
209225 find_in_prelude ( db, & root_def_map, & def_map, ItemInNs :: Types ( module_id. into ( ) ) , from)
210226 {
211- return value;
227+ return value. zip ( Some ( Stable ) ) ;
212228 }
213229 calculate_best_path (
214230 db,
@@ -301,11 +317,19 @@ fn calculate_best_path(
301317 mut prefixed : Option < PrefixKind > ,
302318 prefer_no_std : bool ,
303319 scope_name : Option < Name > ,
304- ) -> Option < ModPath > {
320+ ) -> Option < ( ModPath , Stability ) > {
305321 if max_len <= 1 {
306322 return None ;
307323 }
308324 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+ } ;
309333 // Recursive case:
310334 // - otherwise, look for modules containing (reexporting) it and import it from one of those
311335 if item. krate ( db) == Some ( from. krate ) {
@@ -328,14 +352,14 @@ fn calculate_best_path(
328352 prefixed,
329353 prefer_no_std,
330354 ) {
331- path. push_segment ( name) ;
355+ path. 0 . push_segment ( name) ;
332356
333- let new_path = match best_path {
357+ let new_path = match best_path. take ( ) {
334358 Some ( best_path) => select_best_path ( best_path, path, prefer_no_std) ,
335359 None => path,
336360 } ;
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) ;
339363 }
340364 }
341365 } else {
@@ -354,7 +378,7 @@ fn calculate_best_path(
354378
355379 // Determine best path for containing module and append last segment from `info`.
356380 // 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 (
358382 db,
359383 def_map,
360384 visited_modules,
@@ -367,16 +391,19 @@ fn calculate_best_path(
367391 ) ?;
368392 cov_mark:: hit!( partially_imported) ;
369393 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+ ) )
371398 } )
372399 } ) ;
373400
374401 for path in extern_paths {
375- let new_path = match best_path {
402+ let new_path = match best_path. take ( ) {
376403 Some ( best_path) => select_best_path ( best_path, path, prefer_no_std) ,
377404 None => path,
378405 } ;
379- best_path = Some ( new_path) ;
406+ update_best_path ( & mut best_path, new_path) ;
380407 }
381408 }
382409 if let Some ( module) = item. module ( db) {
@@ -387,15 +414,24 @@ fn calculate_best_path(
387414 }
388415 match prefixed. map ( PrefixKind :: prefix) {
389416 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 ) )
391418 } ) ,
392419 None => best_path,
393420 }
394421}
395422
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+ }
397433 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 ( ) ) {
399435 ( Some ( old) , Some ( new) ) if STD_CRATES . contains ( old) && STD_CRATES . contains ( new) => {
400436 let rank = match prefer_no_std {
401437 false => |name : & Name | match name {
@@ -416,7 +452,7 @@ fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -
416452 match nrank. cmp ( & orank) {
417453 Ordering :: Less => old_path,
418454 Ordering :: Equal => {
419- if new_path. len ( ) < old_path. len ( ) {
455+ if new_path. 0 . len ( ) < old_path. 0 . len ( ) {
420456 new_path
421457 } else {
422458 old_path
@@ -426,7 +462,7 @@ fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -
426462 }
427463 }
428464 _ => {
429- if new_path. len ( ) < old_path. len ( ) {
465+ if new_path. 0 . len ( ) < old_path. 0 . len ( ) {
430466 new_path
431467 } else {
432468 old_path
@@ -1360,4 +1396,29 @@ pub mod ops {
13601396 "std::ops::Deref" ,
13611397 ) ;
13621398 }
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+ }
13631424}
0 commit comments