Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 45d5109

Browse files
authored
Rollup merge of #145573 - veluca93:unsafe-force-target-feature, r=davidtwco
Add an experimental unsafe(force_target_feature) attribute. This uses the feature gate for #143352, but is described in rust-lang/rfcs#3820 which is strongly tied to the experiment.
2 parents f0a4148 + 291da71 commit 45d5109

File tree

21 files changed

+262
-61
lines changed

21 files changed

+262
-61
lines changed

‎compiler/rustc_ast_lowering/src/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1596,7 +1596,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
15961596
let safety = self.lower_safety(h.safety, default_safety);
15971597

15981598
// Treat safe `#[target_feature]` functions as unsafe, but also remember that we did so.
1599-
let safety = if find_attr!(attrs, AttributeKind::TargetFeature { .. })
1599+
let safety = if find_attr!(attrs, AttributeKind::TargetFeature { was_forced:false,.. })
16001600
&& safety.is_safe()
16011601
&& !self.tcx.sess.target.is_like_wasm
16021602
{

‎compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -376,57 +376,68 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
376376
}
377377
}
378378

379+
fn parse_tf_attribute<'c, S: Stage>(
380+
cx: &'c mut AcceptContext<'_, '_, S>,
381+
args: &'c ArgParser<'_>,
382+
) -> impl IntoIterator<Item = (Symbol, Span)> + 'c {
383+
let mut features = Vec::new();
384+
let ArgParser::List(list) = args else {
385+
cx.expected_list(cx.attr_span);
386+
return features;
387+
};
388+
if list.is_empty() {
389+
cx.warn_empty_attribute(cx.attr_span);
390+
return features;
391+
}
392+
for item in list.mixed() {
393+
let Some(name_value) = item.meta_item() else {
394+
cx.expected_name_value(item.span(), Some(sym::enable));
395+
return features;
396+
};
397+
398+
// Validate name
399+
let Some(name) = name_value.path().word_sym() else {
400+
cx.expected_name_value(name_value.path().span(), Some(sym::enable));
401+
return features;
402+
};
403+
if name != sym::enable {
404+
cx.expected_name_value(name_value.path().span(), Some(sym::enable));
405+
return features;
406+
}
407+
408+
// Use value
409+
let Some(name_value) = name_value.args().name_value() else {
410+
cx.expected_name_value(item.span(), Some(sym::enable));
411+
return features;
412+
};
413+
let Some(value_str) = name_value.value_as_str() else {
414+
cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
415+
return features;
416+
};
417+
for feature in value_str.as_str().split(",") {
418+
features.push((Symbol::intern(feature), item.span()));
419+
}
420+
}
421+
features
422+
}
423+
379424
pub(crate) struct TargetFeatureParser;
380425

381426
impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
382427
type Item = (Symbol, Span);
383428
const PATH: &[Symbol] = &[sym::target_feature];
384-
const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::TargetFeature(items, span);
429+
const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::TargetFeature {
430+
features: items,
431+
attr_span: span,
432+
was_forced: false,
433+
};
385434
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
386435

387436
fn extend<'c>(
388437
cx: &'c mut AcceptContext<'_, '_, S>,
389438
args: &'c ArgParser<'_>,
390439
) -> impl IntoIterator<Item = Self::Item> + 'c {
391-
let mut features = Vec::new();
392-
let ArgParser::List(list) = args else {
393-
cx.expected_list(cx.attr_span);
394-
return features;
395-
};
396-
if list.is_empty() {
397-
cx.warn_empty_attribute(cx.attr_span);
398-
return features;
399-
}
400-
for item in list.mixed() {
401-
let Some(name_value) = item.meta_item() else {
402-
cx.expected_name_value(item.span(), Some(sym::enable));
403-
return features;
404-
};
405-
406-
// Validate name
407-
let Some(name) = name_value.path().word_sym() else {
408-
cx.expected_name_value(name_value.path().span(), Some(sym::enable));
409-
return features;
410-
};
411-
if name != sym::enable {
412-
cx.expected_name_value(name_value.path().span(), Some(sym::enable));
413-
return features;
414-
}
415-
416-
// Use value
417-
let Some(name_value) = name_value.args().name_value() else {
418-
cx.expected_name_value(item.span(), Some(sym::enable));
419-
return features;
420-
};
421-
let Some(value_str) = name_value.value_as_str() else {
422-
cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
423-
return features;
424-
};
425-
for feature in value_str.as_str().split(",") {
426-
features.push((Symbol::intern(feature), item.span()));
427-
}
428-
}
429-
features
440+
parse_tf_attribute(cx, args)
430441
}
431442

432443
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
@@ -440,3 +451,30 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
440451
Warn(Target::MacroDef),
441452
]);
442453
}
454+
455+
pub(crate) struct ForceTargetFeatureParser;
456+
457+
impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
458+
type Item = (Symbol, Span);
459+
const PATH: &[Symbol] = &[sym::force_target_feature];
460+
const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::TargetFeature {
461+
features: items,
462+
attr_span: span,
463+
was_forced: true,
464+
};
465+
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
466+
467+
fn extend<'c>(
468+
cx: &'c mut AcceptContext<'_, '_, S>,
469+
args: &'c ArgParser<'_>,
470+
) -> impl IntoIterator<Item = Self::Item> + 'c {
471+
parse_tf_attribute(cx, args)
472+
}
473+
474+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
475+
Allow(Target::Fn),
476+
Allow(Target::Method(MethodKind::Inherent)),
477+
Allow(Target::Method(MethodKind::Trait { body: true })),
478+
Allow(Target::Method(MethodKind::TraitImpl)),
479+
]);
480+
}

‎compiler/rustc_attr_parsing/src/context.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use crate::attributes::allow_unstable::{
1919
};
2020
use crate::attributes::body::CoroutineParser;
2121
use crate::attributes::codegen_attrs::{
22-
ColdParser, CoverageParser, ExportNameParser, NakedParser,NoMangleParser,OptimizeParser,
23-
TargetFeatureParser, TrackCallerParser, UsedParser,
22+
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser,NakedParser,
23+
NoMangleParser,OptimizeParser,TargetFeatureParser, TrackCallerParser, UsedParser,
2424
};
2525
use crate::attributes::confusables::ConfusablesParser;
2626
use crate::attributes::deprecation::DeprecationParser;
@@ -157,6 +157,7 @@ attribute_parsers!(
157157
// tidy-alphabetical-start
158158
Combine<AllowConstFnUnstableParser>,
159159
Combine<AllowInternalUnstableParser>,
160+
Combine<ForceTargetFeatureParser>,
160161
Combine<ReprParser>,
161162
Combine<TargetFeatureParser>,
162163
Combine<UnstableFeatureBoundParser>,

‎compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,15 +193,15 @@ fn process_builtin_attrs(
193193
}
194194
}
195195
AttributeKind::Optimize(optimize, _) => codegen_fn_attrs.optimize = *optimize,
196-
AttributeKind::TargetFeature(features, attr_span) => {
196+
AttributeKind::TargetFeature{features, attr_span, was_forced } => {
197197
let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else {
198198
tcx.dcx().span_delayed_bug(*attr_span, "target_feature applied to non-fn");
199199
continue;
200200
};
201201
let safe_target_features =
202202
matches!(sig.header.safety, hir::HeaderSafety::SafeTargetFeatures);
203203
codegen_fn_attrs.safe_target_features = safe_target_features;
204-
if safe_target_features {
204+
if safe_target_features && !was_forced {
205205
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
206206
// The `#[target_feature]` attribute is allowed on
207207
// WebAssembly targets on all functions. Prior to stabilizing
@@ -232,6 +232,7 @@ fn process_builtin_attrs(
232232
tcx,
233233
did,
234234
features,
235+
*was_forced,
235236
rust_target_features,
236237
&mut codegen_fn_attrs.target_features,
237238
);
@@ -462,7 +463,7 @@ fn check_result(
462463
.collect(),
463464
) {
464465
let span =
465-
find_attr!(tcx.get_all_attrs(did), AttributeKind::TargetFeature(_, span) => *span)
466+
find_attr!(tcx.get_all_attrs(did), AttributeKind::TargetFeature{attr_span: span, ..} => *span)
466467
.unwrap_or_else(|| tcx.def_span(did));
467468

468469
tcx.dcx()

‎compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
33
use rustc_hir::attrs::InstructionSetAttr;
44
use rustc_hir::def::DefKind;
55
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
6-
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
6+
use rustc_middle::middle::codegen_fn_attrs::{TargetFeature,TargetFeatureKind};
77
use rustc_middle::query::Providers;
88
use rustc_middle::ty::TyCtxt;
99
use rustc_session::Session;
@@ -22,6 +22,7 @@ pub(crate) fn from_target_feature_attr(
2222
tcx: TyCtxt<'_>,
2323
did: LocalDefId,
2424
features: &[(Symbol, Span)],
25+
was_forced: bool,
2526
rust_target_features: &UnordMap<String, target_features::Stability>,
2627
target_features: &mut Vec<TargetFeature>,
2728
) {
@@ -88,7 +89,14 @@ pub(crate) fn from_target_feature_attr(
8889
}
8990
}
9091
}
91-
target_features.push(TargetFeature { name, implied: name != feature })
92+
let kind = if name != feature {
93+
TargetFeatureKind::Implied
94+
} else if was_forced {
95+
TargetFeatureKind::Forced
96+
} else {
97+
TargetFeatureKind::Enabled
98+
};
99+
target_features.push(TargetFeature { name, kind })
92100
}
93101
}
94102
}

‎compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
744744
template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"),
745745
ErrorPreceding, EncodeCrossCrate::No
746746
),
747+
gated!(
748+
unsafe force_target_feature, Normal, template!(List: &[r#"enable = "name""#]),
749+
DuplicatesOk, EncodeCrossCrate::No, effective_target_features, experimental!(force_target_feature)
750+
),
747751
gated!(
748752
sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding,
749753
EncodeCrossCrate::No, sanitize, experimental!(sanitize),

‎compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,8 @@ declare_features! (
480480
(unstable, doc_cfg_hide, "1.57.0", Some(43781)),
481481
/// Allows `#[doc(masked)]`.
482482
(unstable, doc_masked, "1.21.0", Some(44027)),
483+
/// Allows features to allow target_feature to better interact with traits.
484+
(incomplete, effective_target_features, "CURRENT_RUSTC_VERSION", Some(143352)),
483485
/// Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }`
484486
(incomplete, ergonomic_clones, "1.87.0", Some(132290)),
485487
/// Allows exhaustive pattern matching on types that contain uninhabited types.

‎compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,9 @@ pub enum AttributeKind {
524524
/// Represents `#[rustc_std_internal_symbol]`.
525525
StdInternalSymbol(Span),
526526

527-
/// Represents `#[target_feature(enable = "...")]`
528-
TargetFeature(ThinVec<(Symbol, Span)>, Span),
527+
/// Represents `#[target_feature(enable = "...")]` and
528+
/// `#[unsafe(force_target_feature(enable = "...")]`.
529+
TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool },
529530

530531
/// Represents `#[track_caller]`
531532
TrackCaller(Span),

‎compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl AttributeKind {
7878
SpecializationTrait(..) => No,
7979
Stability { .. } => Yes,
8080
StdInternalSymbol(..) => No,
81-
TargetFeature(..) => No,
81+
TargetFeature{ .. } => No,
8282
TrackCaller(..) => Yes,
8383
TypeConst(..) => Yes,
8484
UnsafeSpecializationMarker(..) => No,

‎compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,23 @@ pub struct CodegenFnAttrs {
7272
pub patchable_function_entry: Option<PatchableFunctionEntry>,
7373
}
7474

75+
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable, PartialEq, Eq)]
76+
pub enum TargetFeatureKind {
77+
/// The feature is implied by another feature, rather than explicitly added by the
78+
/// `#[target_feature]` attribute
79+
Implied,
80+
/// The feature is added by the regular `target_feature` attribute.
81+
Enabled,
82+
/// The feature is added by the unsafe `force_target_feature` attribute.
83+
Forced,
84+
}
85+
7586
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
7687
pub struct TargetFeature {
7788
/// The name of the target feature (e.g. "avx")
7889
pub name: Symbol,
79-
/// The feature is implied by another feature, rather than explicitly added by the
80-
/// `#[target_feature]` attribute
81-
pub implied: bool,
90+
/// The way this feature was enabled.
91+
pub kind: TargetFeatureKind,
8292
}
8393

8494
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /