@@ -5,6 +5,7 @@ use rustc_ast::{
55    self  as  ast,  CRATE_NODE_ID ,  Crate ,  ItemKind ,  MetaItemInner ,  MetaItemKind ,  ModKind ,  NodeId ,  Path , 
66} ; 
77use  rustc_ast_pretty:: pprust; 
8+ use  rustc_attr_data_structures:: { self  as  attr,  Stability } ; 
89use  rustc_data_structures:: fx:: FxHashSet ; 
910use  rustc_data_structures:: unord:: UnordSet ; 
1011use  rustc_errors:: codes:: * ; 
@@ -110,6 +111,7 @@ pub(crate) struct ImportSuggestion {
110111    pub  via_import :  bool , 
111112    /// An extra note that should be issued if this item is suggested 
112113     pub  note :  Option < String > , 
114+     pub  is_stable :  bool , 
113115} 
114116
115117/// Adjust the impl span so that just the `impl` keyword is taken by removing 
@@ -1172,13 +1174,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11721174            ThinVec :: <ast:: PathSegment >:: new( ) , 
11731175            true , 
11741176            start_did. is_local( )  || !self . tcx. is_doc_hidden( start_did) , 
1177+             true , 
11751178        ) ] ; 
11761179        let  mut  worklist_via_import = vec ! [ ] ; 
11771180
1178-         while  let  Some ( ( in_module,  path_segments,  accessible,  doc_visible) )  = match  worklist. pop ( )  { 
1179-             None  => worklist_via_import. pop ( ) , 
1180-             Some ( x)  => Some ( x) , 
1181-         }  { 
1181+         while  let  Some ( ( in_module,  path_segments,  accessible,  doc_visible,  is_stable) )  =
1182+             match  worklist. pop ( )  { 
1183+                 None  => worklist_via_import. pop ( ) , 
1184+                 Some ( x)  => Some ( x) , 
1185+             } 
1186+         { 
11821187            let  in_module_is_extern = !in_module. def_id ( ) . is_local ( ) ; 
11831188            in_module. for_each_child ( self ,  |this,  ident,  ns,  name_binding| { 
11841189                // Avoid non-importable candidates. 
@@ -1258,6 +1263,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12581263                        candidates. remove ( idx) ; 
12591264                    } 
12601265
1266+                     let  is_stable = if  is_stable
1267+                         && let  Some ( did)  = did
1268+                         && this. is_stable ( did,  path. span ) 
1269+                     { 
1270+                         true 
1271+                     }  else  { 
1272+                         false 
1273+                     } ; 
1274+ 
1275+                     // Rreplace unstable suggestions if we meet a new stable one, 
1276+                     // and do nothing if any other situation. For example, if we 
1277+                     // meet `std::ops::Range` after `std::range::legacy::Range`, 
1278+                     // we will remove the latter and then insert the former. 
1279+                     if  is_stable
1280+                         && let  Some ( idx)  = candidates
1281+                             . iter ( ) 
1282+                             . position ( |v :  & ImportSuggestion | v. did  == did && !v. is_stable ) 
1283+                     { 
1284+                         candidates. remove ( idx) ; 
1285+                     } 
1286+ 
12611287                    if  candidates. iter ( ) . all ( |v :  & ImportSuggestion | v. did  != did)  { 
12621288                        // See if we're recommending TryFrom, TryInto, or FromIterator and add 
12631289                        // a note about editions 
@@ -1289,6 +1315,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12891315                            doc_visible :  child_doc_visible, 
12901316                            note, 
12911317                            via_import, 
1318+                             is_stable, 
12921319                        } ) ; 
12931320                    } 
12941321                } 
@@ -1315,8 +1342,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13151342                    if  !is_extern_crate_that_also_appears_in_prelude || alias_import { 
13161343                        // add the module to the lookup 
13171344                        if  seen_modules. insert ( module. def_id ( ) )  { 
1318-                             if  via_import {  & mut  worklist_via_import }  else  {  & mut  worklist } 
1319-                                 . push ( ( module,  path_segments,  child_accessible,  child_doc_visible) ) ; 
1345+                             if  via_import {  & mut  worklist_via_import }  else  {  & mut  worklist } . push ( 
1346+                                 ( 
1347+                                     module, 
1348+                                     path_segments, 
1349+                                     child_accessible, 
1350+                                     child_doc_visible, 
1351+                                     is_stable && this. is_stable ( module. def_id ( ) ,  name_binding. span ) , 
1352+                                 ) , 
1353+                             ) ; 
13201354                        } 
13211355                    } 
13221356                } 
@@ -1326,6 +1360,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13261360        candidates
13271361    } 
13281362
1363+     fn  is_stable ( & self ,  did :  DefId ,  span :  Span )  -> bool  { 
1364+         if  did. is_local ( )  { 
1365+             return  true ; 
1366+         } 
1367+ 
1368+         match  self . tcx . lookup_stability ( did)  { 
1369+             Some ( Stability  { 
1370+                 level :  attr:: StabilityLevel :: Unstable  {  implied_by,  .. } , 
1371+                 feature, 
1372+                 ..
1373+             } )  => { 
1374+                 if  span. allows_unstable ( feature)  { 
1375+                     true 
1376+                 }  else  if  self . tcx . features ( ) . enabled ( feature)  { 
1377+                     true 
1378+                 }  else  if  let  Some ( implied_by)  = implied_by
1379+                     && self . tcx . features ( ) . enabled ( implied_by) 
1380+                 { 
1381+                     true 
1382+                 }  else  { 
1383+                     false 
1384+                 } 
1385+             } 
1386+             Some ( _)  => true , 
1387+             None  => false , 
1388+         } 
1389+     } 
1390+ 
13291391    /// When name resolution fails, this method can be used to look up candidate 
13301392     /// entities with the expected name. It allows filtering them using the 
13311393     /// supplied predicate (which should be used to only accept the types of 
0 commit comments