@@ -10,7 +10,7 @@ use rustc_middle::query::Providers;
10
10
use rustc_middle:: ty:: TyCtxt ;
11
11
use rustc_session:: parse:: feature_err;
12
12
use rustc_span:: { Span , Symbol , sym} ;
13
- use rustc_target:: target_features;
13
+ use rustc_target:: target_features:: { self , Stability } ;
14
14
15
15
use crate :: errors;
16
16
@@ -150,13 +150,37 @@ pub(crate) fn provide(providers: &mut Providers) {
150
150
let target = & tcx. sess . target ;
151
151
if tcx. sess . opts . actually_rustdoc {
152
152
// 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
160
184
} else {
161
185
tcx. sess
162
186
. target
0 commit comments