@@ -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
@@ -150,13 +150,37 @@ pub(crate) fn provide(providers: &mut Providers) {
150150 let target = & tcx. sess . target ;
151151 if tcx. sess . opts . actually_rustdoc {
152152 // HACK: rustdoc would like to pretend that we have all the target features, so we
153- // have to merge all the lists into one. The result has a "random" stability
154- // (depending on the order in which we consider features); all places that check
155- // target stability are expected to check `actually_rustdoc` and do nothing when
156- // that is set.
157- rustc_target:: target_features:: all_rust_features ( )
158- . map ( |( a, b) | ( a. to_string ( ) , b. compute_toggleability ( target) ) )
159- . collect ( )
153+ // have to merge all the lists into one. To ensure an unstable target never prevents
154+ // a stable one from working, we merge the stability info of all instances of the
155+ // same target feature name, with the "most stable" taking precedence. And then we
156+ // hope that this doesn't cause issues anywhere else in the compiler...
157+ let mut result: UnordMap < String , Stability < _ > > = Default :: default ( ) ;
158+ for ( name, stability) in rustc_target:: target_features:: all_rust_features ( ) {
159+ use std:: collections:: hash_map:: Entry ;
160+ match result. entry ( name. to_owned ( ) ) {
161+ Entry :: Vacant ( vacant_entry) => {
162+ vacant_entry. insert ( stability. compute_toggleability ( target) ) ;
163+ }
164+ Entry :: Occupied ( mut occupied_entry) => {
165+ // Merge the two stabilities, "more stable" taking precedence.
166+ match ( occupied_entry. get ( ) , & stability) {
167+ ( Stability :: Stable { .. } , _)
168+ | (
169+ Stability :: Unstable { .. } ,
170+ Stability :: Unstable { .. } | Stability :: Forbidden { .. } ,
171+ )
172+ | ( Stability :: Forbidden { .. } , Stability :: Forbidden { .. } ) => {
173+ // The stability in the entry is at least as good as the new one, just keep it.
174+ }
175+ _ => {
176+ // Overwrite stabilite.
177+ occupied_entry. insert ( stability. compute_toggleability ( target) ) ;
178+ }
179+ }
180+ }
181+ }
182+ }
183+ result
160184 } else {
161185 tcx. sess
162186 . target
0 commit comments