From 2d887a5c5ca65287bb40dc5b2d108e2bb2dd6719 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 16 Nov 2024 10:00:16 +0100 Subject: generalize 'forbidden feature' concept so that even (un)stable feature can be invalid to toggle Also rename some things for extra clarity --- compiler/rustc_codegen_gcc/src/errors.rs | 1 + compiler/rustc_codegen_gcc/src/gcc_util.rs | 18 ++++++++++-------- compiler/rustc_codegen_gcc/src/lib.rs | 11 ++++++----- 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'compiler/rustc_codegen_gcc/src') diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 7a586b5b04c..56849cc8610 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -28,6 +28,7 @@ pub(crate) struct UnstableCTargetFeature<'a> { #[diag(codegen_gcc_forbidden_ctarget_feature)] pub(crate) struct ForbiddenCTargetFeature<'a> { pub feature: &'a str, + pub reason: &'a str, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 65279c9495a..3717e12020f 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -5,7 +5,7 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_session::Session; -use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; +use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use smallvec::{SmallVec, smallvec}; use crate::errors::{ @@ -94,13 +94,15 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec {} - Some((_, Stability::Unstable(_), _)) => { - // An unstable feature. Warn about using it. - sess.dcx().emit_warn(UnstableCTargetFeature { feature }); - } - Some((_, Stability::Forbidden { .. }, _)) => { - sess.dcx().emit_err(ForbiddenCTargetFeature { feature }); + Some((_, stability, _)) => { + if let Err(reason) = stability.compute(&sess.target).allow_toggle() { + sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); + } else if stability.requires_nightly().is_some() { + // An unstable feature. Warn about using it. (It makes little sense + // to hard-error here since we just warn about fully unknown + // features above). + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } } } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 452e92bffa2..764e84be1fe 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend { .join(sess) } - fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec { - target_features(sess, allow_unstable, &self.target_info) + fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec { + target_features_cfg(sess, allow_unstable, &self.target_info) } } @@ -472,7 +472,8 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { } } -pub fn target_features( +/// Returns the features that should be set in `cfg(target_feature)`. +fn target_features_cfg( sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo, @@ -481,9 +482,9 @@ pub fn target_features( sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.is_supported()) + .filter(|(_, gate, _)| gate.in_cfg()) .filter_map(|&(feature, gate, _)| { - if sess.is_nightly_build() || allow_unstable || gate.is_stable() { + if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { Some(feature) } else { None -- cgit 1.4.1-3-g733a5 From 60eca2c5758a736559a60b7552833d20b0895763 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Dec 2024 11:02:22 +0100 Subject: apply review feedback --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 4 ++- compiler/rustc_codegen_llvm/src/llvm_util.rs | 8 ++++-- compiler/rustc_codegen_ssa/src/target_features.rs | 4 +-- compiler/rustc_target/src/target_features.rs | 34 +++++++++++++++-------- 4 files changed, 32 insertions(+), 18 deletions(-) (limited to 'compiler/rustc_codegen_gcc/src') diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 3717e12020f..88e5eefd7a1 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -95,7 +95,9 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec { - if let Err(reason) = stability.compute(&sess.target).allow_toggle() { + if let Err(reason) = + stability.compute_toggleability(&sess.target).allow_toggle() + { sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); } else if stability.requires_nightly().is_some() { // An unstable feature. Warn about using it. (It makes little sense diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 3f53856f98d..bfec7d708cf 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -717,12 +717,14 @@ pub(crate) fn global_llvm_features( sess.dcx().emit_warn(unknown_feature); } Some((_, stability, _)) => { - if let Err(reason) = stability.compute(&sess.target).allow_toggle() { + if let Err(reason) = + stability.compute_toggleability(&sess.target).allow_toggle() + { sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); } else if stability.requires_nightly().is_some() { - // An unstable feature. Warn about using it. (It makes little sense + // An unstable feature. Warn about using it. It makes little sense // to hard-error here since we just warn about fully unknown - // features above). + // features above. sess.dcx().emit_warn(UnstableCTargetFeature { feature }); } } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b3057325bd6..fa600ec7166 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -153,14 +153,14 @@ pub(crate) fn provide(providers: &mut Providers) { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all rustc_target::target_features::all_rust_features() - .map(|(a, b)| (a.to_string(), b.compute(target))) + .map(|(a, b)| (a.to_string(), b.compute_toggleability(target))) .collect() } else { tcx.sess .target .rust_target_features() .iter() - .map(|&(a, b, _)| (a.to_string(), b.compute(target))) + .map(|&(a, b, _)| (a.to_string(), b.compute_toggleability(target))) .collect() } }, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index d5da130aa6c..b8b0e0c7d59 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -17,17 +17,17 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"]; /// Stability information for target features. -/// `AllowToggle` is the type storing whether (un)stable features can be toggled: +/// `Toggleability` is the type storing whether (un)stable features can be toggled: /// this is initially a function since it can depend on `Target`, but for stable hashing /// it needs to be something hashable to we have to make the type generic. #[derive(Debug, Clone, Copy)] -pub enum Stability { +pub enum Stability { /// This target feature is stable, it can be used in `#[target_feature]` and /// `#[cfg(target_feature)]`. Stable { - /// When enabling/dsiabling the feature via `-Ctarget-feature` or `#[target_feature]`, + /// When enabling/disabling the feature via `-Ctarget-feature` or `#[target_feature]`, /// determine if that is allowed. - allow_toggle: AllowToggle, + allow_toggle: Toggleability, }, /// This target feature is unstable. It is only present in `#[cfg(target_feature)]` on /// nightly and using it in `#[target_feature]` requires enabling the given nightly feature. @@ -36,7 +36,7 @@ pub enum Stability { /// feature gate! nightly_feature: Symbol, /// See `Stable::allow_toggle` comment above. - allow_toggle: AllowToggle, + allow_toggle: Toggleability, }, /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be /// set in the basic target definition. It is never set in `cfg(target_feature)`. Used in @@ -50,7 +50,7 @@ pub type StabilityUncomputed = Stability Result<(), &'static str> /// `Stability` where `allow_toggle` has already been computed. pub type StabilityComputed = Stability>; -impl> HashStable for Stability { +impl> HashStable for Stability { #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { std::mem::discriminant(self).hash_stable(hcx, hasher); @@ -69,15 +69,22 @@ impl> HashStable for Stability Stability { - /// Returns whether the feature can be queried in `cfg` ever. - /// (It might still be nightly-only even if this returns `true`). +impl Stability { + /// Returns whether the feature can be used in `cfg(target_feature)` ever. + /// (It might still be nightly-only even if this returns `true`, so make sure to also check + /// `requires_nightly`.) pub fn in_cfg(self) -> bool { !matches!(self, Stability::Forbidden { .. }) } - /// Returns the nightly feature that is required to toggle or query this target feature. Ensure - /// to also check `allow_toggle()` before allowing to toggle! + /// Returns the nightly feature that is required to toggle this target feature via + /// `#[target_feature]`/`-Ctarget-feature` or to test it via `cfg(target_feature)`. + /// (For `cfg` we only care whether the feature is nightly or not, we don't require + /// the feature gate to actually be enabled when using a nightly compiler.) + /// + /// Before calling this, ensure the feature is even permitted for this use: + /// - for `#[target_feature]`/`-Ctarget-feature`, check `allow_toggle()` + /// - for `cfg(target_feature)`, check `in_cfg` pub fn requires_nightly(self) -> Option { match self { Stability::Unstable { nightly_feature, .. } => Some(nightly_feature), @@ -88,7 +95,7 @@ impl Stability { } impl StabilityUncomputed { - pub fn compute(self, target: &Target) -> StabilityComputed { + pub fn compute_toggleability(self, target: &Target) -> StabilityComputed { use Stability::*; match self { Stable { allow_toggle } => Stable { allow_toggle: allow_toggle(target) }, @@ -101,6 +108,9 @@ impl StabilityUncomputed { } impl StabilityComputed { + /// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`. + /// (It might still be nightly-only even if this returns `true`, so make sure to also check + /// `requires_nightly`.) pub fn allow_toggle(self) -> Result<(), &'static str> { match self { Stability::Stable { allow_toggle } => allow_toggle, -- cgit 1.4.1-3-g733a5