@@ -10,7 +10,7 @@ use rustc_middle::query::Providers;
1010use  rustc_middle:: ty:: TyCtxt ; 
1111use  rustc_session:: parse:: feature_err; 
1212use  rustc_span:: { Span ,  Symbol ,  sym} ; 
13- use  rustc_target:: target_features; 
13+ use  rustc_target:: target_features:: { self ,   Stability } ; 
1414
1515use  crate :: errors; 
1616
@@ -87,10 +87,7 @@ pub(crate) fn from_target_feature_attr(
8787                    // But ensure the ABI does not forbid enabling this. 
8888                    // Here we do assume that LLVM doesn't add even more implied features 
8989                    // we don't know about, at least no features that would have ABI effects! 
90-                     // We skip this check in rustdoc, like we skip all target feature related checks. 
91-                     if  !tcx. sess . opts . actually_rustdoc 
92-                         && abi_feature_constraints. incompatible . contains ( & name. as_str ( ) ) 
93-                     { 
90+                     if  abi_feature_constraints. incompatible . contains ( & name. as_str ( ) )  { 
9491                        tcx. dcx ( ) . emit_err ( errors:: ForbiddenTargetFeatureAttr  { 
9592                            span :  item. span ( ) , 
9693                            feature :  name. as_str ( ) , 
@@ -146,13 +143,37 @@ pub(crate) fn provide(providers: &mut Providers) {
146143            assert_eq ! ( cnum,  LOCAL_CRATE ) ; 
147144            if  tcx. sess . opts . actually_rustdoc  { 
148145                // HACK: rustdoc would like to pretend that we have all the target features, so we 
149-                 // have to merge all the lists into one. The result has a "random" stability 
150-                 // (depending on the order in which we consider features); all places that check 
151-                 // target stability are expected to check `actually_rustdoc` and do nothing when 
152-                 // that is set. 
153-                 rustc_target:: target_features:: all_rust_features ( ) 
154-                     . map ( |( a,  b) | ( a. to_string ( ) ,  b) ) 
155-                     . collect ( ) 
146+                 // have to merge all the lists into one. To ensure an unstable target never prevents 
147+                 // a stable one from working, we merge the stability info of all instances of the 
148+                 // same target feature name, with the "most stable" taking precedence. And then we 
149+                 // hope that this doesn't cause issues anywhere else in the compiler... 
150+                 let  mut  result:  UnordMap < String ,  Stability >  = Default :: default ( ) ; 
151+                 for  ( name,  stability)  in  rustc_target:: target_features:: all_rust_features ( )  { 
152+                     use  std:: collections:: hash_map:: Entry ; 
153+                     match  result. entry ( name. to_owned ( ) )  { 
154+                         Entry :: Vacant ( vacant_entry)  => { 
155+                             vacant_entry. insert ( stability) ; 
156+                         } 
157+                         Entry :: Occupied ( mut  occupied_entry)  => { 
158+                             // Merge the two stabilities, "more stable" taking precedence. 
159+                             match  ( occupied_entry. get ( ) ,  stability)  { 
160+                                 ( Stability :: Stable ,  _) 
161+                                 | ( 
162+                                     Stability :: Unstable  {  .. } , 
163+                                     Stability :: Unstable  {  .. }  | Stability :: Forbidden  {  .. } , 
164+                                 ) 
165+                                 | ( Stability :: Forbidden  {  .. } ,  Stability :: Forbidden  {  .. } )  => { 
166+                                     // The stability in the entry is at least as good as the new one, just keep it. 
167+                                 } 
168+                                 _ => { 
169+                                     // Overwrite stabilite. 
170+                                     occupied_entry. insert ( stability) ; 
171+                                 } 
172+                             } 
173+                         } 
174+                     } 
175+                 } 
176+                 result
156177            }  else  { 
157178                tcx. sess 
158179                    . target 
0 commit comments