about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src/target_features.rs
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-11-16 10:00:16 +0100
committerRalf Jung <post@ralfj.de>2024-12-11 22:11:15 +0100
commit2d887a5c5ca65287bb40dc5b2d108e2bb2dd6719 (patch)
treeaf562288d549ff410de0ed4bd055d3fb6ba17279 /compiler/rustc_codegen_ssa/src/target_features.rs
parent1f3bf231e160b9869e2a85260fd6805304bfcee2 (diff)
downloadrust-2d887a5c5ca65287bb40dc5b2d108e2bb2dd6719.tar.gz
rust-2d887a5c5ca65287bb40dc5b2d108e2bb2dd6719.zip
generalize 'forbidden feature' concept so that even (un)stable feature can be invalid to toggle
Also rename some things for extra clarity
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/target_features.rs')
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs53
1 files changed, 23 insertions, 30 deletions
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index eee7cc75400..b3057325bd6 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_span::Span;
 use rustc_span::symbol::{Symbol, sym};
-use rustc_target::target_features::{self, Stability};
+use rustc_target::target_features;
 
 use crate::errors;
 
@@ -20,7 +20,7 @@ use crate::errors;
 pub(crate) fn from_target_feature_attr(
     tcx: TyCtxt<'_>,
     attr: &ast::Attribute,
-    rust_target_features: &UnordMap<String, target_features::Stability>,
+    rust_target_features: &UnordMap<String, target_features::StabilityComputed>,
     target_features: &mut Vec<TargetFeature>,
 ) {
     let Some(list) = attr.meta_item_list() else { return };
@@ -63,32 +63,24 @@ pub(crate) fn from_target_feature_attr(
                 return None;
             };
 
-            // Only allow target features whose feature gates have been enabled.
-            let allowed = match stability {
-                Stability::Forbidden { .. } => false,
-                Stability::Stable => true,
-                Stability::Unstable(name) => rust_features.enabled(*name),
-            };
-            if !allowed {
-                match stability {
-                    Stability::Stable => unreachable!(),
-                    &Stability::Unstable(lang_feature_name) => {
-                        feature_err(
-                            &tcx.sess,
-                            lang_feature_name,
-                            item.span(),
-                            format!("the target feature `{feature}` is currently unstable"),
-                        )
-                        .emit();
-                    }
-                    Stability::Forbidden { reason } => {
-                        tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
-                            span: item.span(),
-                            feature,
-                            reason,
-                        });
-                    }
-                }
+            // Only allow target features whose feature gates have been enabled
+            // and which are permitted to be toggled.
+            if let Err(reason) = stability.allow_toggle() {
+                tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
+                    span: item.span(),
+                    feature,
+                    reason,
+                });
+            } else if let Some(nightly_feature) = stability.requires_nightly()
+                && !rust_features.enabled(nightly_feature)
+            {
+                feature_err(
+                    &tcx.sess,
+                    nightly_feature,
+                    item.span(),
+                    format!("the target feature `{feature}` is currently unstable"),
+                )
+                .emit();
             }
             Some(Symbol::intern(feature))
         }));
@@ -156,18 +148,19 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         rust_target_features: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
+            let target = &tcx.sess.target;
             if tcx.sess.opts.actually_rustdoc {
                 // 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))
+                    .map(|(a, b)| (a.to_string(), b.compute(target)))
                     .collect()
             } else {
                 tcx.sess
                     .target
                     .rust_target_features()
                     .iter()
-                    .map(|&(a, b, _)| (a.to_string(), b))
+                    .map(|&(a, b, _)| (a.to_string(), b.compute(target)))
                     .collect()
             }
         },