@@ -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,24 @@ 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+ if is_stable
1276+ // Remove unstable match if exists
1277+ && let Some ( idx) = candidates
1278+ . iter ( )
1279+ . position ( |v : & ImportSuggestion | v. did == did && !v. is_stable )
1280+ {
1281+ candidates. remove ( idx) ;
1282+ }
1283+
12611284 if candidates. iter ( ) . all ( |v : & ImportSuggestion | v. did != did) {
12621285 // See if we're recommending TryFrom, TryInto, or FromIterator and add
12631286 // a note about editions
@@ -1289,6 +1312,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12891312 doc_visible : child_doc_visible,
12901313 note,
12911314 via_import,
1315+ is_stable,
12921316 } ) ;
12931317 }
12941318 }
@@ -1315,8 +1339,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13151339 if !is_extern_crate_that_also_appears_in_prelude || alias_import {
13161340 // add the module to the lookup
13171341 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) ) ;
1342+ if via_import { & mut worklist_via_import } else { & mut worklist } . push (
1343+ (
1344+ module,
1345+ path_segments,
1346+ child_accessible,
1347+ child_doc_visible,
1348+ is_stable && this. is_stable ( module. def_id ( ) , name_binding. span ) ,
1349+ ) ,
1350+ ) ;
13201351 }
13211352 }
13221353 }
@@ -1326,6 +1357,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13261357 candidates
13271358 }
13281359
1360+ fn is_stable ( & self , did : DefId , span : Span ) -> bool {
1361+ if did. is_local ( ) {
1362+ return true ;
1363+ }
1364+
1365+ match self . tcx . lookup_stability ( did) {
1366+ Some ( Stability {
1367+ level : attr:: StabilityLevel :: Unstable { implied_by, .. } ,
1368+ feature,
1369+ ..
1370+ } ) => {
1371+ if span. allows_unstable ( feature) {
1372+ true
1373+ } else if self . tcx . features ( ) . enabled ( feature) {
1374+ true
1375+ } else if let Some ( implied_by) = implied_by
1376+ && self . tcx . features ( ) . enabled ( implied_by)
1377+ {
1378+ true
1379+ } else {
1380+ false
1381+ }
1382+ }
1383+ Some ( _) => true ,
1384+ None => false ,
1385+ }
1386+ }
1387+
13291388 /// When name resolution fails, this method can be used to look up candidate
13301389 /// entities with the expected name. It allows filtering them using the
13311390 /// supplied predicate (which should be used to only accept the types of
0 commit comments