Skip to content

Commit 4782383

Browse files
committed
Require annotating struct-tf functions explicitly.
1 parent bd23503 commit 4782383

File tree

12 files changed

+68
-47
lines changed

12 files changed

+68
-47
lines changed

Diff for: compiler/rustc_codegen_ssa/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
243243
codegen_ssa_target_feature_disable_or_enable =
244244
the target features {$features} must all be either enabled or disabled together
245245
246-
codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
246+
codegen_ssa_target_feature_safe_trait = `#[target_feature(enable = ..)]` cannot be applied to safe trait method
247247
.label = cannot be applied to safe trait method
248248
.label_def = not an `unsafe` function
249249

Diff for: compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
250250
&& let Some(fn_sig) = fn_sig()
251251
&& fn_sig.skip_binder().safety() == hir::Safety::Safe
252252
{
253-
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
253+
if attr.meta_item_list().is_some_and(|list| {
254+
list.len() == 1 && list[0].ident().is_some_and(|x| x.name == sym::from_args)
255+
}) {
256+
// #[target_feature(from_args)] can be applied to safe functions and safe
257+
// trait methods.
258+
} else if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
254259
// The `#[target_feature]` attribute is allowed on
255260
// WebAssembly targets on all functions, including safe
256261
// ones. Other targets require that `#[target_feature]` is
@@ -289,6 +294,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
289294
attr,
290295
supported_target_features,
291296
&mut codegen_fn_attrs.target_features,
297+
Some(&mut codegen_fn_attrs.target_features_from_args),
292298
);
293299
}
294300
sym::linkage => {
@@ -599,7 +605,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
599605
}
600606
}
601607

602-
if let Some(sig) = fn_sig_outer() {
608+
if let Some(sig) = fn_sig_outer()
609+
&& codegen_fn_attrs.target_features_from_args
610+
{
603611
let mut additional_tf = vec![];
604612
for ty in sig.skip_binder().inputs().skip_binder() {
605613
extend_with_struct_target_features(
@@ -806,7 +814,7 @@ fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeatur
806814
let mut features = vec![];
807815
let supported_features = tcx.supported_target_features(LOCAL_CRATE);
808816
for attr in tcx.get_attrs(def_id, sym::target_feature) {
809-
from_target_feature(tcx, attr, supported_features, &mut features);
817+
from_target_feature(tcx, attr, supported_features, &mut features, None);
810818
}
811819
tcx.arena.alloc_slice(&features)
812820
}

Diff for: compiler/rustc_codegen_ssa/src/target_features.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub(crate) fn from_target_feature(
2020
attr: &ast::Attribute,
2121
supported_target_features: &UnordMap<String, Option<Symbol>>,
2222
target_features: &mut Vec<TargetFeature>,
23+
mut features_from_args: Option<&mut bool>,
2324
) {
2425
let Some(list) = attr.meta_item_list() else { return };
2526
let bad_item = |span| {
@@ -33,6 +34,14 @@ pub(crate) fn from_target_feature(
3334
let rust_features = tcx.features();
3435
let mut added_target_features = Vec::new();
3536
for item in list {
37+
if let Some(ref mut from_args) = features_from_args
38+
&& item.ident().is_some_and(|x| x.name == sym::from_args)
39+
&& tcx.features().struct_target_features
40+
{
41+
**from_args = true;
42+
continue;
43+
}
44+
3645
// Only `enable = ...` is accepted in the meta-item list.
3746
if !item.has_name(sym::enable) {
3847
bad_item(item.span());
@@ -144,7 +153,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
144153
tcx.arena.alloc(target_features)
145154
}
146155

147-
/// Checks the function annotated with `#[target_feature]` is not a safe
156+
/// Checks the function annotated with `#[target_feature(enable = ...)]` is not a safe
148157
/// trait method implementation, reporting an error if it is.
149158
pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
150159
if let DefKind::AssocFn = tcx.def_kind(id) {

Diff for: compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub struct CodegenFnAttrs {
4949
/// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
5050
/// the function entry.
5151
pub patchable_function_entry: Option<PatchableFunctionEntry>,
52+
/// Whether the target features can be extended through the arguments of the function.
53+
pub target_features_from_args: bool,
5254
}
5355

5456
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -156,6 +158,7 @@ impl CodegenFnAttrs {
156158
instruction_set: None,
157159
alignment: None,
158160
patchable_function_entry: None,
161+
target_features_from_args: false,
159162
}
160163
}
161164

Diff for: compiler/rustc_mir_build/src/check_unsafety.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -589,14 +589,11 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
589589
.copied()
590590
.filter(|feature| missing.contains(feature))
591591
.collect();
592-
self.requires_unsafe(
593-
expr.span,
594-
ConstructingTargetFeaturesTypeWith {
595-
adt: adt_def.did(),
596-
missing,
597-
build_enabled,
598-
},
599-
);
592+
self.requires_unsafe(expr.span, ConstructingTargetFeaturesTypeWith {
593+
adt: adt_def.did(),
594+
missing,
595+
build_enabled,
596+
});
600597
}
601598
}
602599
}

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ symbols! {
946946
frem_algebraic,
947947
frem_fast,
948948
from,
949+
from_args,
949950
from_desugaring,
950951
from_fn,
951952
from_iter,

Diff for: tests/assembly/struct-target-features.rs

+8
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@ struct Avx {}
1515
#[target_feature(enable = "fma")]
1616
struct Fma {}
1717

18+
#[target_feature(from_args)]
1819
pub fn add_simple(_: Avx, v: __m256) -> __m256 {
1920
// CHECK-NOT: call
2021
// CHECK: vaddps
2122
unsafe { _mm256_add_ps(v, v) }
2223
}
2324

25+
// Test that the features don't get inherited from the arguments without the attribute.
26+
pub fn add_simple_noattr(_: Avx, v: __m256) -> __m256 {
27+
// CHECK: call
28+
unsafe { _mm256_add_ps(v, v) }
29+
}
30+
31+
#[target_feature(from_args)]
2432
pub fn add_fma_combined(_: &Avx, _: &Fma, v: __m256) -> (__m256, __m256) {
2533
// CHECK-NOT: call
2634
// CHECK-DAG: vaddps

Diff for: tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `#[target_feature(..)]` cannot be applied to safe trait method
1+
error: `#[target_feature(enable = ..)]` cannot be applied to safe trait method
22
--> $DIR/trait-impl.rs:13:5
33
|
44
LL | #[target_feature(enable = "sse2")]
@@ -7,7 +7,7 @@ LL |
77
LL | fn foo(&self) {}
88
| ------------- not an `unsafe` function
99

10-
error: `#[target_feature(..)]` cannot be applied to safe trait method
10+
error: `#[target_feature(enable = ..)]` cannot be applied to safe trait method
1111
--> $DIR/trait-impl.rs:22:5
1212
|
1313
LL | #[target_feature(enable = "sse2")]

Diff for: tests/ui/target-feature/struct-target-features-crate.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
//@ aux-build: struct-target-features-crate-dep.rs
33
//@ check-pass
44
#![feature(target_feature_11)]
5+
#![feature(struct_target_features)]
6+
//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes
57

68
extern crate struct_target_features_crate_dep;
79

810
#[target_feature(enable = "avx")]
911
fn avx() {}
1012

13+
#[target_feature(from_args)]
1114
fn f(_: struct_target_features_crate_dep::Avx) {
1215
avx();
1316
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/struct-target-features-crate.rs:5:12
3+
|
4+
LL | #![feature(struct_target_features)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #129107 <https://github.com/rust-lang/rust/issues/129107> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

Diff for: tests/ui/target-feature/struct-target-features.rs

+9-22
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,22 @@ impl TFAssociatedType for () {
2525
type Assoc = Avx;
2626
}
2727

28+
#[target_feature(from_args)]
2829
fn avx_self(_: <() as TFAssociatedType>::Assoc) {
2930
avx();
3031
}
3132

33+
#[target_feature(from_args)]
3234
fn avx_avx(_: Avx) {
3335
avx();
3436
}
3537

38+
#[target_feature(from_args)]
3639
extern "C" fn bad_fun(_: Avx) {}
37-
//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI
3840

3941
#[inline(always)]
4042
//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]`
43+
#[target_feature(from_args)]
4144
fn inline_fun(_: Avx) {}
4245
//~^ ERROR cannot use a struct with target features in a #[inline(always)] function
4346

@@ -46,6 +49,7 @@ trait Simd {
4649
}
4750

4851
impl Simd for Avx {
52+
#[target_feature(from_args)]
4953
fn do_something(&self) {
5054
unsafe {
5155
println!("{:?}", _mm256_setzero_ps());
@@ -54,31 +58,15 @@ impl Simd for Avx {
5458
}
5559

5660
impl Simd for Sse {
61+
#[target_feature(from_args)]
5762
fn do_something(&self) {
5863
unsafe {
5964
println!("{:?}", _mm_setzero_ps());
6065
}
6166
}
6267
}
6368

64-
struct WithAvx {
65-
#[allow(dead_code)]
66-
avx: Avx,
67-
}
68-
69-
impl Simd for WithAvx {
70-
fn do_something(&self) {
71-
unsafe {
72-
println!("{:?}", _mm256_setzero_ps());
73-
}
74-
}
75-
}
76-
77-
#[inline(never)]
78-
fn dosomething<S: Simd>(simd: &S) {
79-
simd.do_something();
80-
}
81-
69+
#[target_feature(from_args)]
8270
fn avxfn(_: &Avx) {
8371
// This is not unsafe because we already have the feature at function-level.
8472
let _ = Avx {};
@@ -91,10 +79,9 @@ fn main() {
9179
if is_x86_feature_detected!("avx") {
9280
let avx = unsafe { Avx {} };
9381
avxfn(&avx);
94-
dosomething(&avx);
95-
dosomething(&WithAvx { avx });
82+
avx.do_something();
9683
}
9784
if is_x86_feature_detected!("sse") {
98-
dosomething(&unsafe { Sse {} })
85+
unsafe { Sse {} }.do_something();
9986
}
10087
}

Diff for: tests/ui/target-feature/struct-target-features.stderr

+4-10
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,26 @@ LL | #![feature(struct_target_features)]
77
= note: see issue #129107 <https://github.com/rust-lang/rust/issues/129107> for more information
88
= note: `#[warn(incomplete_features)]` on by default
99

10-
error: cannot use a struct with target features in a function with non-Rust ABI
11-
--> $DIR/struct-target-features.rs:36:1
12-
|
13-
LL | extern "C" fn bad_fun(_: Avx) {}
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15-
1610
error: cannot use a struct with target features in a #[inline(always)] function
17-
--> $DIR/struct-target-features.rs:41:1
11+
--> $DIR/struct-target-features.rs:44:1
1812
|
1913
LL | fn inline_fun(_: Avx) {}
2014
| ^^^^^^^^^^^^^^^^^^^^^
2115

2216
error: cannot use `#[inline(always)]` with `#[target_feature]`
23-
--> $DIR/struct-target-features.rs:39:1
17+
--> $DIR/struct-target-features.rs:41:1
2418
|
2519
LL | #[inline(always)]
2620
| ^^^^^^^^^^^^^^^^^
2721

2822
error[E0133]: initializing type `Avx` with `#[target_feature]` is unsafe and requires unsafe function or block
29-
--> $DIR/struct-target-features.rs:88:5
23+
--> $DIR/struct-target-features.rs:76:5
3024
|
3125
LL | Avx {};
3226
| ^^^^^^ call to function with `#[target_feature]`
3327
|
3428
= note: the target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]`
3529

36-
error: aborting due to 4 previous errors; 1 warning emitted
30+
error: aborting due to 3 previous errors; 1 warning emitted
3731

3832
For more information about this error, try `rustc --explain E0133`.

0 commit comments

Comments
 (0)