diff options
| author | Ralf Jung <post@ralfj.de> | 2024-09-02 11:45:59 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-11-04 22:56:47 +0100 |
| commit | ffad9aac27ff8a78f5d751bf88250470e2e9d790 (patch) | |
| tree | 32e348977a254c1e5cc14310bbcef11c0bfa2eb9 /compiler/rustc_codegen_ssa/src | |
| parent | 2dece5bb62f234f5622a08289c5a3d1555cd7843 (diff) | |
| download | rust-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.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/errors.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/target_features.rs | 54 |
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() } }, |
