Add an experimental unsafe(force_target_feature) attribute.

This uses the feature gate for
https://github.com/rust-lang/rust/issues/143352, but is described in
https://github.com/rust-lang/rfcs/pull/3820 which is strongly tied to
the experiment.
This commit is contained in:
Luca Versari
2025-08-18 15:09:45 +02:00
parent 6ba0ce4094
commit 291da71b2a
21 changed files with 262 additions and 61 deletions

View File

@@ -193,7 +193,7 @@ fn process_builtin_attrs(
}
}
AttributeKind::Optimize(optimize, _) => codegen_fn_attrs.optimize = *optimize,
AttributeKind::TargetFeature(features, attr_span) => {
AttributeKind::TargetFeature { features, attr_span, was_forced } => {
let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else {
tcx.dcx().span_delayed_bug(*attr_span, "target_feature applied to non-fn");
continue;
@@ -201,7 +201,7 @@ fn process_builtin_attrs(
let safe_target_features =
matches!(sig.header.safety, hir::HeaderSafety::SafeTargetFeatures);
codegen_fn_attrs.safe_target_features = safe_target_features;
if safe_target_features {
if safe_target_features && !was_forced {
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
// The `#[target_feature]` attribute is allowed on
// WebAssembly targets on all functions. Prior to stabilizing
@@ -232,6 +232,7 @@ fn process_builtin_attrs(
tcx,
did,
features,
*was_forced,
rust_target_features,
&mut codegen_fn_attrs.target_features,
);
@@ -462,7 +463,7 @@ fn check_result(
.collect(),
) {
let span =
find_attr!(tcx.get_all_attrs(did), AttributeKind::TargetFeature(_, span) => *span)
find_attr!(tcx.get_all_attrs(did), AttributeKind::TargetFeature{attr_span: span, ..} => *span)
.unwrap_or_else(|| tcx.def_span(did));
tcx.dcx()

View File

@@ -3,7 +3,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir::attrs::InstructionSetAttr;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
use rustc_middle::middle::codegen_fn_attrs::{TargetFeature, TargetFeatureKind};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
@@ -22,6 +22,7 @@ pub(crate) fn from_target_feature_attr(
tcx: TyCtxt<'_>,
did: LocalDefId,
features: &[(Symbol, Span)],
was_forced: bool,
rust_target_features: &UnordMap<String, target_features::Stability>,
target_features: &mut Vec<TargetFeature>,
) {
@@ -88,7 +89,14 @@ pub(crate) fn from_target_feature_attr(
}
}
}
target_features.push(TargetFeature { name, implied: name != feature })
let kind = if name != feature {
TargetFeatureKind::Implied
} else if was_forced {
TargetFeatureKind::Forced
} else {
TargetFeatureKind::Enabled
};
target_features.push(TargetFeature { name, kind })
}
}
}