Skip to content

Commit 72465b0

Browse files
committed
Prohibit #[default] in invalid places
1 parent 5ae2371 commit 72465b0

File tree

3 files changed

+131
-29
lines changed

3 files changed

+131
-29
lines changed

compiler/rustc_builtin_macros/src/deriving/default.rs

+37-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33

44
use rustc_ast::ptr::P;
5+
use rustc_ast::walk_list;
56
use rustc_ast::EnumDef;
67
use rustc_ast::VariantData;
78
use rustc_ast::{Expr, MetaItem};
@@ -19,6 +20,8 @@ pub fn expand_deriving_default(
1920
item: &Annotatable,
2021
push: &mut dyn FnMut(Annotatable),
2122
) {
23+
item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
24+
2225
let inline = cx.meta_word(span, sym::inline);
2326
let attrs = vec![cx.attribute(inline)];
2427
let trait_def = TraitDef {
@@ -184,9 +187,12 @@ fn extract_default_variant<'a>(
184187
};
185188

186189
if !matches!(variant.data, VariantData::Unit(..)) {
187-
cx.struct_span_err(variant.ident.span, "`#[default]` may only be used on unit variants")
188-
.help("consider a manual implementation of `Default`")
189-
.emit();
190+
cx.struct_span_err(
191+
variant.ident.span,
192+
"the `#[default]` attribute may only be used on unit enum variants",
193+
)
194+
.help("consider a manual implementation of `Default`")
195+
.emit();
190196

191197
return Err(());
192198
}
@@ -253,3 +259,31 @@ fn validate_default_attribute(
253259
}
254260
Ok(())
255261
}
262+
263+
struct DetectNonVariantDefaultAttr<'a, 'b> {
264+
cx: &'a ExtCtxt<'b>,
265+
}
266+
267+
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
268+
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
269+
if attr.has_name(kw::Default) {
270+
self.cx
271+
.struct_span_err(
272+
attr.span,
273+
"the `#[default]` attribute may only be used on unit enum variants",
274+
)
275+
.emit();
276+
}
277+
278+
rustc_ast::visit::walk_attribute(self, attr);
279+
}
280+
fn visit_variant(&mut self, v: &'a rustc_ast::Variant) {
281+
self.visit_ident(v.ident);
282+
self.visit_vis(&v.vis);
283+
self.visit_variant_data(&v.data);
284+
walk_list!(self, visit_anon_const, &v.disr_expr);
285+
for attr in &v.attrs {
286+
rustc_ast::visit::walk_attribute(self, attr);
287+
}
288+
}
289+
}

src/test/ui/macros/macros-nonfatal-errors.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,40 @@
55

66
#![feature(asm, llvm_asm)]
77
#![feature(trace_macros, concat_idents)]
8+
#![feature(stmt_expr_attributes, arbitrary_enum_discriminant)]
89
#![feature(derive_default_enum)]
910

11+
#[derive(Default)]
12+
struct DefaultInnerAttrStruct {
13+
#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants
14+
foo: (),
15+
}
16+
17+
#[derive(Default)]
18+
struct DefaultInnerAttrTupleStruct(#[default] ());
19+
//~^ ERROR the `#[default]` attribute may only be used on unit enum variants
20+
21+
#[derive(Default)]
22+
#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants
23+
struct DefaultOuterAttrStruct {}
24+
25+
#[derive(Default)]
26+
#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants
27+
enum DefaultOuterAttrEnum {
28+
#[default]
29+
Foo,
30+
}
31+
32+
#[rustfmt::skip] // needs some work to handle this case
33+
#[repr(u8)]
34+
#[derive(Default)]
35+
enum AttrOnInnerExpression {
36+
Foo = #[default] 0, //~ ERROR the `#[default]` attribute may only be used on unit enum variants
37+
Bar([u8; #[default] 1]), //~ ERROR the `#[default]` attribute may only be used on unit enum variants
38+
#[default]
39+
Baz,
40+
}
41+
1042
#[derive(Default)] //~ ERROR no default declared
1143
enum NoDeclaredDefault {
1244
Foo,
@@ -50,7 +82,7 @@ enum ManyDefaultAttrs {
5082
#[derive(Default)]
5183
enum DefaultHasFields {
5284
#[default]
53-
Foo {}, //~ ERROR `#[default]` may only be used on unit variants
85+
Foo {}, //~ ERROR the `#[default]` attribute may only be used on unit enum variants
5486
Bar,
5587
}
5688

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
1+
error: the `#[default]` attribute may only be used on unit enum variants
2+
--> $DIR/macros-nonfatal-errors.rs:13:5
3+
|
4+
LL | #[default]
5+
| ^^^^^^^^^^
6+
7+
error: the `#[default]` attribute may only be used on unit enum variants
8+
--> $DIR/macros-nonfatal-errors.rs:18:36
9+
|
10+
LL | struct DefaultInnerAttrTupleStruct(#[default] ());
11+
| ^^^^^^^^^^
12+
13+
error: the `#[default]` attribute may only be used on unit enum variants
14+
--> $DIR/macros-nonfatal-errors.rs:22:1
15+
|
16+
LL | #[default]
17+
| ^^^^^^^^^^
18+
19+
error: the `#[default]` attribute may only be used on unit enum variants
20+
--> $DIR/macros-nonfatal-errors.rs:26:1
21+
|
22+
LL | #[default]
23+
| ^^^^^^^^^^
24+
25+
error: the `#[default]` attribute may only be used on unit enum variants
26+
--> $DIR/macros-nonfatal-errors.rs:36:11
27+
|
28+
LL | Foo = #[default] 0,
29+
| ^^^^^^^^^^
30+
31+
error: the `#[default]` attribute may only be used on unit enum variants
32+
--> $DIR/macros-nonfatal-errors.rs:37:14
33+
|
34+
LL | Bar([u8; #[default] 1]),
35+
| ^^^^^^^^^^
36+
137
error: no default declared
2-
--> $DIR/macros-nonfatal-errors.rs:10:10
38+
--> $DIR/macros-nonfatal-errors.rs:42:10
339
|
440
LL | #[derive(Default)]
541
| ^^^^^^^
@@ -8,7 +44,7 @@ LL | #[derive(Default)]
844
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
945

1046
error: multiple declared defaults
11-
--> $DIR/macros-nonfatal-errors.rs:16:10
47+
--> $DIR/macros-nonfatal-errors.rs:48:10
1248
|
1349
LL | #[derive(Default)]
1450
| ^^^^^^^
@@ -26,15 +62,15 @@ LL | Baz,
2662
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
2763

2864
error: `#[default]` attribute does not accept a value
29-
--> $DIR/macros-nonfatal-errors.rs:28:5
65+
--> $DIR/macros-nonfatal-errors.rs:60:5
3066
|
3167
LL | #[default = 1]
3268
| ^^^^^^^^^^^^^^
3369
|
3470
= help: try using `#[default]`
3571

3672
error: multiple `#[default]` attributes
37-
--> $DIR/macros-nonfatal-errors.rs:36:5
73+
--> $DIR/macros-nonfatal-errors.rs:68:5
3874
|
3975
LL | #[default]
4076
| ---------- `#[default]` used here
@@ -45,13 +81,13 @@ LL | Foo,
4581
|
4682
= note: only one `#[default]` attribute is needed
4783
help: try removing this
48-
--> $DIR/macros-nonfatal-errors.rs:35:5
84+
--> $DIR/macros-nonfatal-errors.rs:67:5
4985
|
5086
LL | #[default]
5187
| ^^^^^^^^^^
5288

5389
error: multiple `#[default]` attributes
54-
--> $DIR/macros-nonfatal-errors.rs:46:5
90+
--> $DIR/macros-nonfatal-errors.rs:78:5
5591
|
5692
LL | #[default]
5793
| ---------- `#[default]` used here
@@ -63,7 +99,7 @@ LL | Foo,
6399
|
64100
= note: only one `#[default]` attribute is needed
65101
help: try removing these
66-
--> $DIR/macros-nonfatal-errors.rs:43:5
102+
--> $DIR/macros-nonfatal-errors.rs:75:5
67103
|
68104
LL | #[default]
69105
| ^^^^^^^^^^
@@ -72,16 +108,16 @@ LL | #[default]
72108
LL | #[default]
73109
| ^^^^^^^^^^
74110

75-
error: `#[default]` may only be used on unit variants
76-
--> $DIR/macros-nonfatal-errors.rs:53:5
111+
error: the `#[default]` attribute may only be used on unit enum variants
112+
--> $DIR/macros-nonfatal-errors.rs:85:5
77113
|
78114
LL | Foo {},
79115
| ^^^
80116
|
81117
= help: consider a manual implementation of `Default`
82118

83119
error: default variant must be exhaustive
84-
--> $DIR/macros-nonfatal-errors.rs:61:5
120+
--> $DIR/macros-nonfatal-errors.rs:93:5
85121
|
86122
LL | #[non_exhaustive]
87123
| ----------------- declared `#[non_exhaustive]` here
@@ -91,51 +127,51 @@ LL | Foo,
91127
= help: consider a manual implementation of `Default`
92128

93129
error: asm template must be a string literal
94-
--> $DIR/macros-nonfatal-errors.rs:66:10
130+
--> $DIR/macros-nonfatal-errors.rs:98:10
95131
|
96132
LL | asm!(invalid);
97133
| ^^^^^^^
98134

99135
error: inline assembly must be a string literal
100-
--> $DIR/macros-nonfatal-errors.rs:67:15
136+
--> $DIR/macros-nonfatal-errors.rs:99:15
101137
|
102138
LL | llvm_asm!(invalid);
103139
| ^^^^^^^
104140

105141
error: concat_idents! requires ident args.
106-
--> $DIR/macros-nonfatal-errors.rs:69:5
142+
--> $DIR/macros-nonfatal-errors.rs:101:5
107143
|
108144
LL | concat_idents!("not", "idents");
109145
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
110146

111147
error: argument must be a string literal
112-
--> $DIR/macros-nonfatal-errors.rs:71:17
148+
--> $DIR/macros-nonfatal-errors.rs:103:17
113149
|
114150
LL | option_env!(invalid);
115151
| ^^^^^^^
116152

117153
error: expected string literal
118-
--> $DIR/macros-nonfatal-errors.rs:72:10
154+
--> $DIR/macros-nonfatal-errors.rs:104:10
119155
|
120156
LL | env!(invalid);
121157
| ^^^^^^^
122158

123159
error: expected string literal
124-
--> $DIR/macros-nonfatal-errors.rs:73:10
160+
--> $DIR/macros-nonfatal-errors.rs:105:10
125161
|
126162
LL | env!(foo, abr, baz);
127163
| ^^^
128164

129165
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
130-
--> $DIR/macros-nonfatal-errors.rs:74:5
166+
--> $DIR/macros-nonfatal-errors.rs:106:5
131167
|
132168
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
133169
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
134170
|
135171
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
136172

137173
error: format argument must be a string literal
138-
--> $DIR/macros-nonfatal-errors.rs:76:13
174+
--> $DIR/macros-nonfatal-errors.rs:108:13
139175
|
140176
LL | format!(invalid);
141177
| ^^^^^^^
@@ -146,44 +182,44 @@ LL | format!("{}", invalid);
146182
| ^^^^^
147183

148184
error: argument must be a string literal
149-
--> $DIR/macros-nonfatal-errors.rs:78:14
185+
--> $DIR/macros-nonfatal-errors.rs:110:14
150186
|
151187
LL | include!(invalid);
152188
| ^^^^^^^
153189

154190
error: argument must be a string literal
155-
--> $DIR/macros-nonfatal-errors.rs:80:18
191+
--> $DIR/macros-nonfatal-errors.rs:112:18
156192
|
157193
LL | include_str!(invalid);
158194
| ^^^^^^^
159195

160196
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
161-
--> $DIR/macros-nonfatal-errors.rs:81:5
197+
--> $DIR/macros-nonfatal-errors.rs:113:5
162198
|
163199
LL | include_str!("i'd be quite surprised if a file with this name existed");
164200
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
165201
|
166202
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
167203

168204
error: argument must be a string literal
169-
--> $DIR/macros-nonfatal-errors.rs:82:20
205+
--> $DIR/macros-nonfatal-errors.rs:114:20
170206
|
171207
LL | include_bytes!(invalid);
172208
| ^^^^^^^
173209

174210
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
175-
--> $DIR/macros-nonfatal-errors.rs:83:5
211+
--> $DIR/macros-nonfatal-errors.rs:115:5
176212
|
177213
LL | include_bytes!("i'd be quite surprised if a file with this name existed");
178214
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
179215
|
180216
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
181217

182218
error: trace_macros! accepts only `true` or `false`
183-
--> $DIR/macros-nonfatal-errors.rs:85:5
219+
--> $DIR/macros-nonfatal-errors.rs:117:5
184220
|
185221
LL | trace_macros!(invalid);
186222
| ^^^^^^^^^^^^^^^^^^^^^^^
187223

188-
error: aborting due to 21 previous errors
224+
error: aborting due to 27 previous errors
189225

0 commit comments

Comments
 (0)