Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d898105

Browse files
committedAug 5, 2024·
Implement RFC 3525.
1 parent 64ebd39 commit d898105

File tree

16 files changed

+378
-19
lines changed

16 files changed

+378
-19
lines changed
 

‎compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
22
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
3+
use rustc_data_structures::fx::FxHashSet;
34
use rustc_errors::codes::*;
45
use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage};
56
use rustc_hir as hir;
@@ -16,8 +17,10 @@ use rustc_middle::ty::{self as ty, TyCtxt};
1617
use rustc_session::lint;
1718
use rustc_session::parse::feature_err;
1819
use rustc_span::symbol::Ident;
19-
use rustc_span::{sym, Span};
20+
use rustc_span::{sym, Span, Symbol};
21+
use rustc_target::abi::VariantIdx;
2022
use rustc_target::spec::{abi, SanitizerSet};
23+
use rustc_type_ir::inherent::*;
2124

2225
use crate::errors;
2326
use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
@@ -78,23 +81,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
7881
let mut link_ordinal_span = None;
7982
let mut no_sanitize_span = None;
8083

84+
let fn_sig_outer = || {
85+
use DefKind::*;
86+
87+
let def_kind = tcx.def_kind(did);
88+
if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None }
89+
};
90+
8191
for attr in attrs.iter() {
8292
// In some cases, attribute are only valid on functions, but it's the `check_attr`
8393
// pass that check that they aren't used anywhere else, rather this module.
8494
// In these cases, we bail from performing further checks that are only meaningful for
8595
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
8696
// report a delayed bug, just in case `check_attr` isn't doing its job.
8797
let fn_sig = || {
88-
use DefKind::*;
89-
90-
let def_kind = tcx.def_kind(did);
91-
if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
92-
Some(tcx.fn_sig(did))
93-
} else {
98+
let sig = fn_sig_outer();
99+
if sig.is_none() {
94100
tcx.dcx()
95101
.span_delayed_bug(attr.span, "this attribute can only be applied to functions");
96-
None
97102
}
103+
sig
98104
};
99105

100106
let Some(Ident { name, .. }) = attr.ident() else {
@@ -613,6 +619,57 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
613619
}
614620
}
615621

622+
if tcx.features().struct_target_features
623+
&& let Some(sig) = fn_sig_outer()
624+
{
625+
// Collect target features from types reachable from arguments.
626+
// We define a type as "reachable" if:
627+
// - it is a function argument
628+
// - it is a field of a reachable struct
629+
// - there is a reachable reference to it
630+
// FIXME: we may want to cache the result of this computation.
631+
let mut visited_types = FxHashSet::default();
632+
let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned();
633+
let mut additional_tf = vec![];
634+
635+
while let Some(ty) = reachable_types.pop() {
636+
if visited_types.contains(&ty) {
637+
continue;
638+
}
639+
visited_types.insert(ty);
640+
if ty.is_ref() {
641+
reachable_types.push(ty.builtin_deref(false).unwrap());
642+
} else if matches!(ty.kind(), ty::Tuple(_)) {
643+
reachable_types.extend(ty.tuple_fields().iter());
644+
} else if let ty::Adt(adt_def, args) = ty.kind() {
645+
additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did()));
646+
if adt_def.is_struct() {
647+
reachable_types.extend(
648+
adt_def
649+
.variant(VariantIdx::from_usize(0))
650+
.fields
651+
.iter()
652+
.map(|field| field.ty(tcx, args)),
653+
);
654+
}
655+
}
656+
}
657+
658+
if !additional_tf.is_empty() && !sig.skip_binder().abi().is_rust() {
659+
tcx.dcx().span_err(
660+
tcx.hir().span(tcx.local_def_id_to_hir_id(did)),
661+
"cannot use a struct with target features in a function with non-Rust ABI",
662+
);
663+
}
664+
if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always {
665+
tcx.dcx().span_err(
666+
tcx.hir().span(tcx.local_def_id_to_hir_id(did)),
667+
"cannot use a struct with target features in a #[inline(always)] function",
668+
);
669+
}
670+
codegen_fn_attrs.target_features.extend_from_slice(&additional_tf);
671+
}
672+
616673
// If a function uses #[target_feature] it can't be inlined into general
617674
// purpose functions as they wouldn't have the right target features
618675
// enabled. For that reason we also forbid #[inline(always)] as it can't be
@@ -758,6 +815,20 @@ fn check_link_name_xor_ordinal(
758815
}
759816
}
760817

818+
fn struct_target_features(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol> {
819+
let mut features = vec![];
820+
let supported_features = tcx.supported_target_features(LOCAL_CRATE);
821+
for attr in tcx.get_attrs(def_id, sym::target_feature) {
822+
from_target_feature(tcx, attr, supported_features, &mut features);
823+
}
824+
features
825+
}
826+
761827
pub fn provide(providers: &mut Providers) {
762-
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
828+
*providers = Providers {
829+
codegen_fn_attrs,
830+
should_inherit_track_caller,
831+
struct_target_features,
832+
..*providers
833+
};
763834
}

‎compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
471471
ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
472472
ungated!(
473473
target_feature, Normal, template!(List: r#"enable = "name""#),
474-
DuplicatesOk, EncodeCrossCrate::No,
474+
DuplicatesOk, EncodeCrossCrate::Yes,
475475
),
476476
ungated!(track_caller, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
477477
ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding, EncodeCrossCrate::No),

‎compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,8 @@ declare_features! (
605605
(unstable, strict_provenance, "1.61.0", Some(95228)),
606606
/// Allows string patterns to dereference values to match them.
607607
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
608+
/// Allows structs to carry target_feature information.
609+
(unstable, struct_target_features, "CURRENT_RUSTC_VERSION", Some(871212)) /*FIXME*/,
608610
/// Allows the use of `#[target_feature]` on safe functions.
609611
(unstable, target_feature_11, "1.45.0", Some(69098)),
610612
/// Allows using `#[thread_local]` on `static` items.

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,11 @@ rustc_queries! {
12461246
feedable
12471247
}
12481248

1249+
query struct_target_features(def_id: DefId) -> &'tcx Vec<Symbol> {
1250+
arena_cache
1251+
desc { |tcx| "computing target features for struct `{}`", tcx.def_path_str(def_id) }
1252+
}
1253+
12491254
query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> {
12501255
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
12511256
}

‎compiler/rustc_mir_build/messages.ftl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,17 @@ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed
125125
.note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
126126
.label = initializing type with `rustc_layout_scalar_valid_range` attr
127127
128+
mir_build_initializing_type_with_target_feature_requires_unsafe =
129+
initializing type with `target_feature` attr is unsafe and requires unsafe block
130+
.note = this struct can only be constructed if the corresponding `target_feature`s are available
131+
.label = initializing type with `target_feature` attr
132+
133+
mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
134+
initializing type with `target_feature` attr is unsafe and requires unsafe function or block
135+
.note = this struct can only be constructed if the corresponding `target_feature`s are available
136+
.label = initializing type with `target_feature` attr
137+
138+
128139
mir_build_inline_assembly_requires_unsafe =
129140
use of inline assembly is unsafe and requires unsafe block
130141
.note = inline assembly is entirely unchecked and can cause undefined behavior
@@ -384,6 +395,11 @@ mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe =
384395
.note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior
385396
.label = initializing type with `rustc_layout_scalar_valid_range` attr
386397
398+
mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe =
399+
initializing type with `target_feature` attr is unsafe and requires unsafe block
400+
.note = this struct can only be constructed if the corresponding `target_feature`s are available
401+
.label = initializing type with `target_feature` attr
402+
387403
mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe =
388404
use of inline assembly is unsafe and requires unsafe block
389405
.note = inline assembly is entirely unchecked and can cause undefined behavior

‎compiler/rustc_mir_build/src/check_unsafety.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,16 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
510510
user_ty: _,
511511
fields: _,
512512
base: _,
513-
}) => match self.tcx.layout_scalar_valid_range(adt_def.did()) {
514-
(Bound::Unbounded, Bound::Unbounded) => {}
515-
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
516-
},
513+
}) => {
514+
match self.tcx.layout_scalar_valid_range(adt_def.did()) {
515+
(Bound::Unbounded, Bound::Unbounded) => {}
516+
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
517+
}
518+
if !self.tcx.struct_target_features(adt_def.did()).is_empty() {
519+
self.requires_unsafe(expr.span, ConstructingTargetFeaturesType)
520+
}
521+
}
522+
517523
ExprKind::Closure(box ClosureExpr {
518524
closure_id,
519525
args: _,
@@ -615,6 +621,7 @@ enum UnsafeOpKind {
615621
CallToUnsafeFunction(Option<DefId>),
616622
UseOfInlineAssembly,
617623
InitializingTypeWith,
624+
ConstructingTargetFeaturesType,
618625
UseOfMutableStatic,
619626
UseOfExternStatic,
620627
DerefOfRawPointer,
@@ -696,6 +703,15 @@ impl UnsafeOpKind {
696703
unsafe_not_inherited_note,
697704
},
698705
),
706+
ConstructingTargetFeaturesType => tcx.emit_node_span_lint(
707+
UNSAFE_OP_IN_UNSAFE_FN,
708+
hir_id,
709+
span,
710+
UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe {
711+
span,
712+
unsafe_not_inherited_note,
713+
},
714+
),
699715
UseOfMutableStatic => tcx.emit_node_span_lint(
700716
UNSAFE_OP_IN_UNSAFE_FN,
701717
hir_id,
@@ -853,6 +869,20 @@ impl UnsafeOpKind {
853869
unsafe_not_inherited_note,
854870
});
855871
}
872+
ConstructingTargetFeaturesType if unsafe_op_in_unsafe_fn_allowed => {
873+
dcx.emit_err(
874+
InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
875+
span,
876+
unsafe_not_inherited_note,
877+
},
878+
);
879+
}
880+
ConstructingTargetFeaturesType => {
881+
dcx.emit_err(InitializingTypeWithTargetFeatureRequiresUnsafe {
882+
span,
883+
unsafe_not_inherited_note,
884+
});
885+
}
856886
UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
857887
dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
858888
span,

‎compiler/rustc_mir_build/src/errors.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
8787
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
8888
}
8989

90+
#[derive(LintDiagnostic)]
91+
#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe, code = E0133)]
92+
#[note]
93+
pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe {
94+
#[label]
95+
pub(crate) span: Span,
96+
#[subdiagnostic]
97+
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>,
98+
}
99+
90100
#[derive(LintDiagnostic)]
91101
#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)]
92102
#[note]
@@ -251,6 +261,17 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe {
251261
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
252262
}
253263

264+
#[derive(Diagnostic)]
265+
#[diag(mir_build_initializing_type_with_target_feature_requires_unsafe, code = E0133)]
266+
#[note]
267+
pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafe {
268+
#[primary_span]
269+
#[label]
270+
pub(crate) span: Span,
271+
#[subdiagnostic]
272+
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
273+
}
274+
254275
#[derive(Diagnostic)]
255276
#[diag(
256277
mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
@@ -265,6 +286,20 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
265286
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
266287
}
267288

289+
#[derive(Diagnostic)]
290+
#[diag(
291+
mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
292+
code = E0133
293+
)]
294+
#[note]
295+
pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
296+
#[primary_span]
297+
#[label]
298+
pub(crate) span: Span,
299+
#[subdiagnostic]
300+
pub(crate) unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>,
301+
}
302+
268303
#[derive(Diagnostic)]
269304
#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)]
270305
#[note]

‎compiler/rustc_passes/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,10 @@ passes_should_be_applied_to_fn =
659659
*[false] not a function definition
660660
}
661661
662+
passes_should_be_applied_to_fn_or_unit_struct =
663+
attribute should be applied to a function definition or unit struct
664+
.label = not a function definition or a unit struct
665+
662666
passes_should_be_applied_to_static =
663667
attribute should be applied to a static
664668
.label = not a static

‎compiler/rustc_passes/src/check_attr.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -737,12 +737,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
737737
Target::Field | Target::Arm | Target::MacroDef => {
738738
self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
739739
}
740+
Target::Struct if self.tcx.features().struct_target_features => {
741+
let ty = self.tcx.hir_node(hir_id).expect_item();
742+
match ty.kind {
743+
ItemKind::Struct(data, _) => {
744+
if data.fields().len() != 0 {
745+
self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct {
746+
attr_span: attr.span,
747+
defn_span: span,
748+
});
749+
}
750+
}
751+
_ => {
752+
panic!("Target::Struct for a non-struct");
753+
}
754+
}
755+
}
740756
_ => {
741-
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
742-
attr_span: attr.span,
743-
defn_span: span,
744-
on_crate: hir_id == CRATE_HIR_ID,
745-
});
757+
if self.tcx.features().struct_target_features {
758+
self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct {
759+
attr_span: attr.span,
760+
defn_span: span,
761+
});
762+
} else {
763+
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
764+
attr_span: attr.span,
765+
defn_span: span,
766+
on_crate: hir_id == CRATE_HIR_ID,
767+
});
768+
}
746769
}
747770
}
748771
}

‎compiler/rustc_passes/src/errors.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ pub struct AttrShouldBeAppliedToFn {
8282
pub on_crate: bool,
8383
}
8484

85+
#[derive(Diagnostic)]
86+
#[diag(passes_should_be_applied_to_fn_or_unit_struct)]
87+
pub struct AttrShouldBeAppliedToFnOrUnitStruct {
88+
#[primary_span]
89+
pub attr_span: Span,
90+
#[label]
91+
pub defn_span: Span,
92+
}
93+
8594
#[derive(Diagnostic)]
8695
#[diag(passes_should_be_applied_to_fn, code = E0739)]
8796
pub struct TrackedCallerWrongLocation {

‎compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,6 +1845,7 @@ symbols! {
18451845
stringify,
18461846
struct_field_attributes,
18471847
struct_inherit,
1848+
struct_target_features,
18481849
struct_variant,
18491850
structural_match,
18501851
structural_peq,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//@ compile-flags: -O
2+
//@ assembly-output: emit-asm
3+
//@ only-x86_64
4+
5+
#![crate_type = "lib"]
6+
#![feature(struct_target_features)]
7+
8+
// Check that a struct_target_features type causes the compiler to effectively inline intrinsics.
9+
10+
use std::arch::x86_64::*;
11+
12+
#[target_feature(enable = "avx")]
13+
struct Avx {}
14+
15+
#[target_feature(enable = "fma")]
16+
struct Fma {}
17+
18+
pub fn add_simple(_: Avx, v: __m256) -> __m256 {
19+
// CHECK-NOT: call
20+
// CHECK: vaddps
21+
unsafe { _mm256_add_ps(v, v) }
22+
}
23+
24+
pub fn add_complex_type(_: (&Avx, ()), v: __m256) -> __m256 {
25+
// CHECK-NOT: call
26+
// CHECK: vaddps
27+
unsafe { _mm256_add_ps(v, v) }
28+
}
29+
30+
pub fn add_fma_combined(_: (&Avx, &Fma), v: __m256) -> (__m256, __m256) {
31+
// CHECK-NOT: call
32+
// CHECK-DAG: vaddps
33+
let r1 = unsafe { _mm256_add_ps(v, v) };
34+
// CHECK-DAG: vfmadd213ps
35+
let r2 = unsafe { _mm256_fmadd_ps(v, v, v) };
36+
(r1, r2)
37+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[target_feature(enable = "avx")] //~ ERROR attribute should be applied to a function definition
2+
struct Avx {}
3+
4+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: attribute should be applied to a function definition
2+
--> $DIR/feature-gate-struct-target-features.rs:1:1
3+
|
4+
LL | #[target_feature(enable = "avx")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
LL | struct Avx {}
7+
| ------------- not a function definition
8+
9+
error: aborting due to 1 previous error
10+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//@ only-x86_64
2+
#![feature(struct_target_features)]
3+
4+
use std::arch::x86_64::*;
5+
6+
#[target_feature(enable = "avx")]
7+
//~^ ERROR attribute should be applied to a function definition or unit struct
8+
struct Invalid(u32);
9+
10+
#[target_feature(enable = "avx")]
11+
struct Avx {}
12+
13+
#[target_feature(enable = "sse")]
14+
struct Sse();
15+
16+
extern "C" fn bad_fun(_: Avx) {}
17+
//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI
18+
19+
#[inline(always)]
20+
//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]`
21+
fn inline_fun(_: Avx) {}
22+
//~^ ERROR cannot use a struct with target features in a #[inline(always)] function
23+
24+
trait Simd {
25+
fn do_something(&self);
26+
}
27+
28+
impl Simd for Avx {
29+
fn do_something(&self) {
30+
unsafe {
31+
println!("{:?}", _mm256_setzero_ps());
32+
}
33+
}
34+
}
35+
36+
impl Simd for Sse {
37+
fn do_something(&self) {
38+
unsafe {
39+
println!("{:?}", _mm_setzero_ps());
40+
}
41+
}
42+
}
43+
44+
struct WithAvx {
45+
#[allow(dead_code)]
46+
avx: Avx,
47+
}
48+
49+
impl Simd for WithAvx {
50+
fn do_something(&self) {
51+
unsafe {
52+
println!("{:?}", _mm256_setzero_ps());
53+
}
54+
}
55+
}
56+
57+
#[inline(never)]
58+
fn dosomething<S: Simd>(simd: &S) {
59+
simd.do_something();
60+
}
61+
62+
fn main() {
63+
Avx {};
64+
//~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133]
65+
66+
if is_x86_feature_detected!("avx") {
67+
let avx = unsafe { Avx {} };
68+
dosomething(&avx);
69+
dosomething(&WithAvx { avx });
70+
}
71+
if is_x86_feature_detected!("sse") {
72+
dosomething(&unsafe { Sse {} })
73+
}
74+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: attribute should be applied to a function definition or unit struct
2+
--> $DIR/struct-target-features.rs:6:1
3+
|
4+
LL | #[target_feature(enable = "avx")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
LL |
7+
LL | struct Invalid(u32);
8+
| -------------------- not a function definition or a unit struct
9+
10+
error: cannot use a struct with target features in a function with non-Rust ABI
11+
--> $DIR/struct-target-features.rs:16:1
12+
|
13+
LL | extern "C" fn bad_fun(_: Avx) {}
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
16+
error: cannot use a struct with target features in a #[inline(always)] function
17+
--> $DIR/struct-target-features.rs:21:1
18+
|
19+
LL | fn inline_fun(_: Avx) {}
20+
| ^^^^^^^^^^^^^^^^^^^^^
21+
22+
error: cannot use `#[inline(always)]` with `#[target_feature]`
23+
--> $DIR/struct-target-features.rs:19:1
24+
|
25+
LL | #[inline(always)]
26+
| ^^^^^^^^^^^^^^^^^
27+
28+
error[E0133]: initializing type with `target_feature` attr is unsafe and requires unsafe function or block
29+
--> $DIR/struct-target-features.rs:63:5
30+
|
31+
LL | Avx {};
32+
| ^^^^^^ initializing type with `target_feature` attr
33+
|
34+
= note: this struct can only be constructed if the corresponding `target_feature`s are available
35+
36+
error: aborting due to 5 previous errors
37+
38+
For more information about this error, try `rustc --explain E0133`.

0 commit comments

Comments
 (0)
Please sign in to comment.