Skip to content

Commit c13521b

Browse files
RalfJungcuviper
authored andcommitted
also fix potential issues with mixed stable/unstable target features in rustdoc
(cherry picked from commit 039af88)
1 parent d4de520 commit c13521b

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

compiler/rustc_codegen_ssa/src/target_features.rs

+32-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_middle::query::Providers;
1010
use rustc_middle::ty::TyCtxt;
1111
use rustc_session::parse::feature_err;
1212
use rustc_span::{Span, Symbol, sym};
13-
use rustc_target::target_features;
13+
use rustc_target::target_features::{self, Stability};
1414

1515
use 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

Comments
 (0)