From: Ralf Jung Date: Tue, 25 Feb 2025 19:38:13 +0000 (+0100) Subject: also fix potential issues with mixed stable/unstable target features in rustdoc X-Git-Tag: archive/raspbian/1.85.0+dfsg2-2+rpi1~4 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=07905b9e498fc346755ca65d32fd821034373268;p=rustc.git also fix potential issues with mixed stable/unstable target features in rustdoc (cherry picked from commit 039af88e09f4f4beb47406f4771bffc2e61d800a) --- diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index d673cd6e6b..bffcdca299 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -10,7 +10,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; -use rustc_target::target_features; +use rustc_target::target_features::{self, Stability}; use crate::errors; @@ -150,13 +150,37 @@ pub(crate) fn provide(providers: &mut Providers) { let target = &tcx.sess.target; if tcx.sess.opts.actually_rustdoc { // HACK: rustdoc would like to pretend that we have all the target features, so we - // have to merge all the lists into one. The result has a "random" stability - // (depending on the order in which we consider features); all places that check - // target stability are expected to check `actually_rustdoc` and do nothing when - // that is set. - rustc_target::target_features::all_rust_features() - .map(|(a, b)| (a.to_string(), b.compute_toggleability(target))) - .collect() + // have to merge all the lists into one. To ensure an unstable target never prevents + // a stable one from working, we merge the stability info of all instances of the + // same target feature name, with the "most stable" taking precedence. And then we + // hope that this doesn't cause issues anywhere else in the compiler... + let mut result: UnordMap> = Default::default(); + for (name, stability) in rustc_target::target_features::all_rust_features() { + use std::collections::hash_map::Entry; + match result.entry(name.to_owned()) { + Entry::Vacant(vacant_entry) => { + vacant_entry.insert(stability.compute_toggleability(target)); + } + Entry::Occupied(mut occupied_entry) => { + // Merge the two stabilities, "more stable" taking precedence. + match (occupied_entry.get(), &stability) { + (Stability::Stable { .. }, _) + | ( + Stability::Unstable { .. }, + Stability::Unstable { .. } | Stability::Forbidden { .. }, + ) + | (Stability::Forbidden { .. }, Stability::Forbidden { .. }) => { + // The stability in the entry is at least as good as the new one, just keep it. + } + _ => { + // Overwrite stabilite. + occupied_entry.insert(stability.compute_toggleability(target)); + } + } + } + } + } + result } else { tcx.sess .target