Skip to content

Commit 00cba5b

Browse files
authoredSep 28, 2019
Rollup merge of #64809 - davidtwco:issue-64768-target-feature-const, r=varkor
hir: Disallow `target_feature` on constants Fixes #64768. This PR fixes an ICE when `#[target_feature]` is applied to constants by disallowing this with the same error as when `#[target_feature]` is applied to other places it shouldn't be. I couldn't see anything in the [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2045-target-feature.md) that suggested that `#[target_feature]` should be applicable to constants or any tests that suggested it should, though I might have missed something - if this is desirable in future, it remains possible to remove this error (but for the time being, I think this error is better than an ICE). I also added some extra cases to the test for other places where `#[target_feature]` should not be permitted. cc @gnzlbg
2 parents 5b6a580 + c3368bd commit 00cba5b

8 files changed

+204
-71
lines changed
 

‎src/librustc/hir/check_attr.rs

+52-20
Original file line numberDiff line numberDiff line change
@@ -93,70 +93,102 @@ struct CheckAttrVisitor<'tcx> {
9393
impl CheckAttrVisitor<'tcx> {
9494
/// Checks any attribute.
9595
fn check_attributes(&self, item: &hir::Item, target: Target) {
96-
if target == Target::Fn || target == Target::Const {
97-
self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(item.hir_id));
98-
} else if let Some(a) = item.attrs.iter().find(|a| a.check_name(sym::target_feature)) {
99-
self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
100-
.span_label(item.span, "not a function")
101-
.emit();
102-
}
103-
96+
let mut is_valid = true;
10497
for attr in &item.attrs {
105-
if attr.check_name(sym::inline) {
98+
is_valid &= if attr.check_name(sym::inline) {
10699
self.check_inline(attr, &item.span, target)
107100
} else if attr.check_name(sym::non_exhaustive) {
108101
self.check_non_exhaustive(attr, item, target)
109102
} else if attr.check_name(sym::marker) {
110103
self.check_marker(attr, item, target)
111-
}
104+
} else if attr.check_name(sym::target_feature) {
105+
self.check_target_feature(attr, item, target)
106+
} else {
107+
true
108+
};
109+
}
110+
111+
if !is_valid {
112+
return;
113+
}
114+
115+
if target == Target::Fn {
116+
self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(item.hir_id));
112117
}
113118

114119
self.check_repr(item, target);
115120
self.check_used(item, target);
116121
}
117122

118-
/// Checks if an `#[inline]` is applied to a function or a closure.
119-
fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) {
123+
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
124+
fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) -> bool {
120125
if target != Target::Fn && target != Target::Closure {
121126
struct_span_err!(self.tcx.sess,
122127
attr.span,
123128
E0518,
124129
"attribute should be applied to function or closure")
125130
.span_label(*span, "not a function or closure")
126131
.emit();
132+
false
133+
} else {
134+
true
127135
}
128136
}
129137

130-
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid.
131-
fn check_non_exhaustive(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
138+
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
139+
fn check_non_exhaustive(
140+
&self,
141+
attr: &hir::Attribute,
142+
item: &hir::Item,
143+
target: Target,
144+
) -> bool {
132145
match target {
133-
Target::Struct | Target::Enum => { /* Valid */ },
146+
Target::Struct | Target::Enum => true,
134147
_ => {
135148
struct_span_err!(self.tcx.sess,
136149
attr.span,
137150
E0701,
138151
"attribute can only be applied to a struct or enum")
139152
.span_label(item.span, "not a struct or enum")
140153
.emit();
141-
return;
154+
false
142155
}
143156
}
144157
}
145158

146-
/// Checks if the `#[marker]` attribute on an `item` is valid.
147-
fn check_marker(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
159+
/// Checks if the `#[marker]` attribute on an `item` is valid. Returns `true` if valid.
160+
fn check_marker(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool {
148161
match target {
149-
Target::Trait => { /* Valid */ },
162+
Target::Trait => true,
150163
_ => {
151164
self.tcx.sess
152165
.struct_span_err(attr.span, "attribute can only be applied to a trait")
153166
.span_label(item.span, "not a trait")
154167
.emit();
155-
return;
168+
false
156169
}
157170
}
158171
}
159172

173+
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
174+
fn check_target_feature(
175+
&self,
176+
attr: &hir::Attribute,
177+
item: &hir::Item,
178+
target: Target,
179+
) -> bool {
180+
match target {
181+
Target::Fn => true,
182+
_ => {
183+
self.tcx.sess
184+
.struct_span_err(attr.span, "attribute should be applied to a function")
185+
.span_label(item.span, "not a function")
186+
.emit();
187+
false
188+
},
189+
}
190+
}
191+
160192
/// Checks if the `#[repr]` attributes on `item` are valid.
161193
fn check_repr(&self, item: &hir::Item, target: Target) {
162194
// Extract the names of all repr hints, e.g., [foo, bar, align] for:
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// This test checks that all expected errors occur when there are multiple invalid attributes
2+
// on an item.
3+
4+
#[inline]
5+
//~^ ERROR attribute should be applied to function or closure [E0518]
6+
#[target_feature(enable = "sse2")]
7+
//~^ ERROR attribute should be applied to a function
8+
const FOO: u8 = 0;
9+
10+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0518]: attribute should be applied to function or closure
2+
--> $DIR/multiple-invalid.rs:4:1
3+
|
4+
LL | #[inline]
5+
| ^^^^^^^^^
6+
...
7+
LL | const FOO: u8 = 0;
8+
| ------------------ not a function or closure
9+
10+
error: attribute should be applied to a function
11+
--> $DIR/multiple-invalid.rs:6:1
12+
|
13+
LL | #[target_feature(enable = "sse2")]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
LL |
16+
LL | const FOO: u8 = 0;
17+
| ------------------ not a function
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0518`.

‎src/test/ui/target-feature-wrong.stderr

-50
This file was deleted.
File renamed without changes.

‎src/test/ui/target-feature-gate.stderr ‎src/test/ui/target-feature/gate.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0658]: the target feature `avx512bw` is currently unstable
2-
--> $DIR/target-feature-gate.rs:30:18
2+
--> $DIR/gate.rs:30:18
33
|
44
LL | #[target_feature(enable = "avx512bw")]
55
| ^^^^^^^^^^^^^^^^^^^

‎src/test/ui/target-feature-wrong.rs ‎src/test/ui/target-feature/invalid-attribute.rs

+25
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,31 @@ fn bar() {}
3535
mod another {}
3636
//~^ NOTE not a function
3737

38+
#[target_feature(enable = "sse2")]
39+
//~^ ERROR attribute should be applied to a function
40+
const FOO: usize = 7;
41+
//~^ NOTE not a function
42+
43+
#[target_feature(enable = "sse2")]
44+
//~^ ERROR attribute should be applied to a function
45+
struct Foo;
46+
//~^ NOTE not a function
47+
48+
#[target_feature(enable = "sse2")]
49+
//~^ ERROR attribute should be applied to a function
50+
enum Bar { }
51+
//~^ NOTE not a function
52+
53+
#[target_feature(enable = "sse2")]
54+
//~^ ERROR attribute should be applied to a function
55+
union Qux { f1: u16, f2: u16 }
56+
//~^ NOTE not a function
57+
58+
#[target_feature(enable = "sse2")]
59+
//~^ ERROR attribute should be applied to a function
60+
trait Baz { }
61+
//~^ NOTE not a function
62+
3863
#[inline(always)]
3964
//~^ ERROR: cannot use `#[inline(always)]`
4065
#[target_feature(enable = "sse2")]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
error: malformed `target_feature` attribute input
2+
--> $DIR/invalid-attribute.rs:16:1
3+
|
4+
LL | #[target_feature = "+sse2"]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]`
6+
7+
error: the feature named `foo` is not valid for this target
8+
--> $DIR/invalid-attribute.rs:18:18
9+
|
10+
LL | #[target_feature(enable = "foo")]
11+
| ^^^^^^^^^^^^^^ `foo` is not valid for this target
12+
13+
error: malformed `target_feature` attribute input
14+
--> $DIR/invalid-attribute.rs:21:18
15+
|
16+
LL | #[target_feature(bar)]
17+
| ^^^ help: must be of the form: `enable = ".."`
18+
19+
error: malformed `target_feature` attribute input
20+
--> $DIR/invalid-attribute.rs:23:18
21+
|
22+
LL | #[target_feature(disable = "baz")]
23+
| ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."`
24+
25+
error: `#[target_feature(..)]` can only be applied to `unsafe` functions
26+
--> $DIR/invalid-attribute.rs:27:1
27+
|
28+
LL | #[target_feature(enable = "sse2")]
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions
30+
...
31+
LL | fn bar() {}
32+
| ----------- not an `unsafe` function
33+
34+
error: attribute should be applied to a function
35+
--> $DIR/invalid-attribute.rs:33:1
36+
|
37+
LL | #[target_feature(enable = "sse2")]
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
LL |
40+
LL | mod another {}
41+
| -------------- not a function
42+
43+
error: attribute should be applied to a function
44+
--> $DIR/invalid-attribute.rs:38:1
45+
|
46+
LL | #[target_feature(enable = "sse2")]
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48+
LL |
49+
LL | const FOO: usize = 7;
50+
| --------------------- not a function
51+
52+
error: attribute should be applied to a function
53+
--> $DIR/invalid-attribute.rs:43:1
54+
|
55+
LL | #[target_feature(enable = "sse2")]
56+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
57+
LL |
58+
LL | struct Foo;
59+
| ----------- not a function
60+
61+
error: attribute should be applied to a function
62+
--> $DIR/invalid-attribute.rs:48:1
63+
|
64+
LL | #[target_feature(enable = "sse2")]
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66+
LL |
67+
LL | enum Bar { }
68+
| ------------ not a function
69+
70+
error: attribute should be applied to a function
71+
--> $DIR/invalid-attribute.rs:53:1
72+
|
73+
LL | #[target_feature(enable = "sse2")]
74+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
75+
LL |
76+
LL | union Qux { f1: u16, f2: u16 }
77+
| ------------------------------ not a function
78+
79+
error: attribute should be applied to a function
80+
--> $DIR/invalid-attribute.rs:58:1
81+
|
82+
LL | #[target_feature(enable = "sse2")]
83+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84+
LL |
85+
LL | trait Baz { }
86+
| ------------- not a function
87+
88+
error: cannot use `#[inline(always)]` with `#[target_feature]`
89+
--> $DIR/invalid-attribute.rs:63:1
90+
|
91+
LL | #[inline(always)]
92+
| ^^^^^^^^^^^^^^^^^
93+
94+
error: aborting due to 12 previous errors
95+

0 commit comments

Comments
 (0)
Please sign in to comment.