about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-09-02 11:45:59 +0200
committerRalf Jung <post@ralfj.de>2024-11-04 22:56:47 +0100
commitffad9aac27ff8a78f5d751bf88250470e2e9d790 (patch)
tree32e348977a254c1e5cc14310bbcef11c0bfa2eb9 /compiler/rustc_codegen_ssa/src
parent2dece5bb62f234f5622a08289c5a3d1555cd7843 (diff)
downloadrust-ffad9aac27ff8a78f5d751bf88250470e2e9d790.tar.gz
rust-ffad9aac27ff8a78f5d751bf88250470e2e9d790.zip
mark some target features as 'forbidden' so they cannot be (un)set
For now, this is just a warning, but should become a hard error in the future
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs54
3 files changed, 51 insertions, 26 deletions
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index a5bd3adbcdd..31f8d479f7e 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -20,8 +20,8 @@ use rustc_span::symbol::Ident;
 use rustc_span::{Span, sym};
 use rustc_target::spec::{SanitizerSet, abi};
 
-use crate::errors::{self, MissingFeatures, TargetFeatureDisableOrEnable};
-use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
+use crate::errors;
+use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature_attr};
 
 fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
     use rustc_middle::mir::mono::Linkage::*;
@@ -73,7 +73,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
     }
 
-    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
+    let rust_target_features = tcx.rust_target_features(LOCAL_CRATE);
 
     let mut inline_span = None;
     let mut link_ordinal_span = None;
@@ -281,10 +281,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         check_target_feature_trait_unsafe(tcx, did, attr.span);
                     }
                 }
-                from_target_feature(
+                from_target_feature_attr(
                     tcx,
                     attr,
-                    supported_target_features,
+                    rust_target_features,
                     &mut codegen_fn_attrs.target_features,
                 );
             }
@@ -676,10 +676,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
             .next()
             .map_or_else(|| tcx.def_span(did), |a| a.span);
         tcx.dcx()
-            .create_err(TargetFeatureDisableOrEnable {
+            .create_err(errors::TargetFeatureDisableOrEnable {
                 features,
                 span: Some(span),
-                missing_features: Some(MissingFeatures),
+                missing_features: Some(errors::MissingFeatures),
             })
             .emit();
     }
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index d67cf0e3a6d..670ad39d811 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1019,6 +1019,15 @@ pub(crate) struct TargetFeatureSafeTrait {
 }
 
 #[derive(Diagnostic)]
+#[diag(codegen_ssa_forbidden_target_feature_attr)]
+pub struct ForbiddenTargetFeatureAttr<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub feature: &'a str,
+    pub reason: &'a str,
+}
+
+#[derive(Diagnostic)]
 #[diag(codegen_ssa_failed_to_get_layout)]
 pub struct FailedToGetLayout<'tcx> {
     #[primary_span]
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 0845bcc5749..eee7cc75400 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -11,13 +11,16 @@ 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 crate::errors;
 
-pub(crate) fn from_target_feature(
+/// Compute the enabled target features from the `#[target_feature]` function attribute.
+/// Enabled target features are added to `target_features`.
+pub(crate) fn from_target_feature_attr(
     tcx: TyCtxt<'_>,
     attr: &ast::Attribute,
-    supported_target_features: &UnordMap<String, Option<Symbol>>,
+    rust_target_features: &UnordMap<String, target_features::Stability>,
     target_features: &mut Vec<TargetFeature>,
 ) {
     let Some(list) = attr.meta_item_list() else { return };
@@ -46,12 +49,12 @@ pub(crate) fn from_target_feature(
 
         // We allow comma separation to enable multiple features.
         added_target_features.extend(value.as_str().split(',').filter_map(|feature| {
-            let Some(feature_gate) = supported_target_features.get(feature) else {
+            let Some(stability) = rust_target_features.get(feature) else {
                 let msg = format!("the feature named `{feature}` is not valid for this target");
                 let mut err = tcx.dcx().struct_span_err(item.span(), msg);
                 err.span_label(item.span(), format!("`{feature}` is not valid for this target"));
                 if let Some(stripped) = feature.strip_prefix('+') {
-                    let valid = supported_target_features.contains_key(stripped);
+                    let valid = rust_target_features.contains_key(stripped);
                     if valid {
                         err.help("consider removing the leading `+` in the feature name");
                     }
@@ -61,18 +64,31 @@ pub(crate) fn from_target_feature(
             };
 
             // Only allow target features whose feature gates have been enabled.
-            let allowed = match feature_gate.as_ref().copied() {
-                Some(name) => rust_features.enabled(name),
-                None => true,
+            let allowed = match stability {
+                Stability::Forbidden { .. } => false,
+                Stability::Stable => true,
+                Stability::Unstable(name) => rust_features.enabled(*name),
             };
             if !allowed {
-                feature_err(
-                    &tcx.sess,
-                    feature_gate.unwrap(),
-                    item.span(),
-                    format!("the target feature `{feature}` is currently unstable"),
-                )
-                .emit();
+                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,
+                        });
+                    }
+                }
             }
             Some(Symbol::intern(feature))
         }));
@@ -138,20 +154,20 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId,
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
-        supported_target_features: |tcx, cnum| {
+        rust_target_features: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
             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_known_features()
-                    .map(|(a, b)| (a.to_string(), b.as_feature_name()))
+                rustc_target::target_features::all_rust_features()
+                    .map(|(a, b)| (a.to_string(), b))
                     .collect()
             } else {
                 tcx.sess
                     .target
-                    .supported_target_features()
+                    .rust_target_features()
                     .iter()
-                    .map(|&(a, b, _)| (a.to_string(), b.as_feature_name()))
+                    .map(|&(a, b, _)| (a.to_string(), b))
                     .collect()
             }
         },