Skip to content

Commit 3a94f4c

Browse files
authored
Rollup merge of rust-lang#134364 - estebank:derive-docs, r=fmease
Use E0665 for missing `#[default]` on enum and update doc The docs for E0665 when doing `#[derive(Default]` on an `enum` previously didn't mention `#[default]` at all, or made a distinction between unit variants, that can be annotated, and tuple or struct variants, which cannot. E0665 was not being emitted, we now use it for the same error it belonged to before. ``` error[E0665]: `#[derive(Default)]` on enum with no `#[default]` --> $DIR/macros-nonfatal-errors.rs:42:10 | LL | #[derive(Default)] | ^^^^^^^ LL | / enum NoDeclaredDefault { LL | | Foo, LL | | Bar, LL | | } | |_- this enum needs a unit variant marked with `#[default]` | = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) help: make this unit variant default by placing `#[default]` on it | LL | #[default] Foo, | ++++++++++ help: make this unit variant default by placing `#[default]` on it | LL | #[default] Bar, | ++++++++++ ```
2 parents 00bf74d + 94812f1 commit 3a94f4c

File tree

6 files changed

+95
-52
lines changed

6 files changed

+95
-52
lines changed

compiler/rustc_builtin_macros/messages.ftl

+3-3
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,9 @@ builtin_macros_naked_functions_testing_attribute =
249249
.label = function marked with testing attribute here
250250
.naked_attribute = `#[naked]` is incompatible with testing attributes
251251
252-
builtin_macros_no_default_variant = no default declared
253-
.help = make a unit variant default by placing `#[default]` above it
254-
.suggestion = make `{$ident}` default
252+
builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[default]`
253+
.label = this enum needs a unit variant marked with `#[default]`
254+
.suggestion = make this unit variant default by placing `#[default]` on it
255255
256256
builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi`
257257

compiler/rustc_builtin_macros/src/deriving/default.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ pub(crate) fn expand_deriving_default(
4242
StaticStruct(_, fields) => {
4343
default_struct_substructure(cx, trait_span, substr, fields)
4444
}
45-
StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def),
45+
StaticEnum(enum_def, _) => {
46+
default_enum_substructure(cx, trait_span, enum_def, item.span())
47+
}
4648
_ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"),
4749
}
4850
})),
@@ -96,9 +98,10 @@ fn default_enum_substructure(
9698
cx: &ExtCtxt<'_>,
9799
trait_span: Span,
98100
enum_def: &EnumDef,
101+
item_span: Span,
99102
) -> BlockOrExpr {
100103
let expr = match try {
101-
let default_variant = extract_default_variant(cx, enum_def, trait_span)?;
104+
let default_variant = extract_default_variant(cx, enum_def, trait_span, item_span)?;
102105
validate_default_attribute(cx, default_variant)?;
103106
default_variant
104107
} {
@@ -146,6 +149,7 @@ fn extract_default_variant<'a>(
146149
cx: &ExtCtxt<'_>,
147150
enum_def: &'a EnumDef,
148151
trait_span: Span,
152+
item_span: Span,
149153
) -> Result<&'a rustc_ast::Variant, ErrorGuaranteed> {
150154
let default_variants: SmallVec<[_; 1]> = enum_def
151155
.variants
@@ -163,9 +167,10 @@ fn extract_default_variant<'a>(
163167
.filter(|variant| !attr::contains_name(&variant.attrs, sym::non_exhaustive));
164168

165169
let suggs = possible_defaults
166-
.map(|v| errors::NoDefaultVariantSugg { span: v.span, ident: v.ident })
170+
.map(|v| errors::NoDefaultVariantSugg { span: v.span.shrink_to_lo() })
167171
.collect();
168-
let guar = cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, suggs });
172+
let guar =
173+
cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, item_span, suggs });
169174

170175
return Err(guar);
171176
}

compiler/rustc_builtin_macros/src/errors.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -369,26 +369,21 @@ pub(crate) struct DerivePathArgsValue {
369369
}
370370

371371
#[derive(Diagnostic)]
372-
#[diag(builtin_macros_no_default_variant)]
373-
#[help]
372+
#[diag(builtin_macros_no_default_variant, code = E0665)]
374373
pub(crate) struct NoDefaultVariant {
375374
#[primary_span]
376375
pub(crate) span: Span,
376+
#[label]
377+
pub(crate) item_span: Span,
377378
#[subdiagnostic]
378379
pub(crate) suggs: Vec<NoDefaultVariantSugg>,
379380
}
380381

381382
#[derive(Subdiagnostic)]
382-
#[suggestion(
383-
builtin_macros_suggestion,
384-
code = "#[default] {ident}",
385-
applicability = "maybe-incorrect",
386-
style = "tool-only"
387-
)]
383+
#[suggestion(builtin_macros_suggestion, code = "#[default] ", applicability = "maybe-incorrect")]
388384
pub(crate) struct NoDefaultVariantSugg {
389385
#[primary_span]
390386
pub(crate) span: Span,
391-
pub(crate) ident: Ident,
392387
}
393388

394389
#[derive(Diagnostic)]
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
#### Note: this error code is no longer emitted by the compiler.
2-
3-
The `Default` trait was derived on an enum.
1+
The `Default` trait was derived on an enum without specifying the default
2+
variant.
43

54
Erroneous code example:
65

7-
```compile_fail
6+
```compile_fail,E0665
87
#[derive(Default)]
98
enum Food {
109
Sweet,
@@ -16,18 +15,30 @@ The `Default` cannot be derived on an enum for the simple reason that the
1615
compiler doesn't know which value to pick by default whereas it can for a
1716
struct as long as all its fields implement the `Default` trait as well.
1817

19-
If you still want to implement `Default` on your enum, you'll have to do it "by
20-
hand":
18+
For the case where the desired default variant has no payload, you can
19+
annotate it with `#[default]` to derive it:
2120

2221
```
22+
#[derive(Default)]
2323
enum Food {
24+
#[default]
2425
Sweet,
2526
Salty,
2627
}
28+
```
29+
30+
In the case where the default variant does have a payload, you will have to
31+
implement `Default` on your enum manually:
32+
33+
```
34+
enum Food {
35+
Sweet(i32),
36+
Salty,
37+
}
2738
2839
impl Default for Food {
2940
fn default() -> Food {
30-
Food::Sweet
41+
Food::Sweet(1)
3142
}
3243
}
3344
```

tests/ui/macros/macros-nonfatal-errors.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ enum AttrOnInnerExpression {
3939
Baz,
4040
}
4141

42-
#[derive(Default)] //~ ERROR no default declared
42+
#[derive(Default)] //~ ERROR `#[derive(Default)]` on enum with no `#[default]`
4343
enum NoDeclaredDefault {
4444
Foo,
4545
Bar,
4646
}
4747

48+
#[derive(Default)] //~ ERROR `#[derive(Default)]` on enum with no `#[default]`
49+
enum NoDeclaredDefaultWithoutUnitVariant {
50+
Foo(i32),
51+
Bar(i32),
52+
}
53+
4854
#[derive(Default)] //~ ERROR multiple declared defaults
4955
enum MultipleDefaults {
5056
#[default]

tests/ui/macros/macros-nonfatal-errors.stderr

+54-28
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,43 @@ LL | Bar([u8; #[default] 1]),
4646
|
4747
= help: consider a manual implementation of `Default`
4848

49-
error: no default declared
49+
error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
5050
--> $DIR/macros-nonfatal-errors.rs:42:10
5151
|
52-
LL | #[derive(Default)]
53-
| ^^^^^^^
52+
LL | #[derive(Default)]
53+
| ^^^^^^^
54+
LL | / enum NoDeclaredDefault {
55+
LL | | Foo,
56+
LL | | Bar,
57+
LL | | }
58+
| |_- this enum needs a unit variant marked with `#[default]`
5459
|
55-
= help: make a unit variant default by placing `#[default]` above it
5660
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
61+
help: make this unit variant default by placing `#[default]` on it
62+
|
63+
LL | #[default] Foo,
64+
| ++++++++++
65+
help: make this unit variant default by placing `#[default]` on it
66+
|
67+
LL | #[default] Bar,
68+
| ++++++++++
5769

58-
error: multiple declared defaults
70+
error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
5971
--> $DIR/macros-nonfatal-errors.rs:48:10
6072
|
73+
LL | #[derive(Default)]
74+
| ^^^^^^^
75+
LL | / enum NoDeclaredDefaultWithoutUnitVariant {
76+
LL | | Foo(i32),
77+
LL | | Bar(i32),
78+
LL | | }
79+
| |_- this enum needs a unit variant marked with `#[default]`
80+
|
81+
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
82+
83+
error: multiple declared defaults
84+
--> $DIR/macros-nonfatal-errors.rs:54:10
85+
|
6186
LL | #[derive(Default)]
6287
| ^^^^^^^
6388
...
@@ -74,15 +99,15 @@ LL | Baz,
7499
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
75100

76101
error: `#[default]` attribute does not accept a value
77-
--> $DIR/macros-nonfatal-errors.rs:60:5
102+
--> $DIR/macros-nonfatal-errors.rs:66:5
78103
|
79104
LL | #[default = 1]
80105
| ^^^^^^^^^^^^^^
81106
|
82107
= help: try using `#[default]`
83108

84109
error: multiple `#[default]` attributes
85-
--> $DIR/macros-nonfatal-errors.rs:68:5
110+
--> $DIR/macros-nonfatal-errors.rs:74:5
86111
|
87112
LL | #[default]
88113
| ---------- `#[default]` used here
@@ -93,13 +118,13 @@ LL | Foo,
93118
|
94119
= note: only one `#[default]` attribute is needed
95120
help: try removing this
96-
--> $DIR/macros-nonfatal-errors.rs:67:5
121+
--> $DIR/macros-nonfatal-errors.rs:73:5
97122
|
98123
LL | #[default]
99124
| ^^^^^^^^^^
100125

101126
error: multiple `#[default]` attributes
102-
--> $DIR/macros-nonfatal-errors.rs:78:5
127+
--> $DIR/macros-nonfatal-errors.rs:84:5
103128
|
104129
LL | #[default]
105130
| ---------- `#[default]` used here
@@ -111,7 +136,7 @@ LL | Foo,
111136
|
112137
= note: only one `#[default]` attribute is needed
113138
help: try removing these
114-
--> $DIR/macros-nonfatal-errors.rs:75:5
139+
--> $DIR/macros-nonfatal-errors.rs:81:5
115140
|
116141
LL | #[default]
117142
| ^^^^^^^^^^
@@ -121,15 +146,15 @@ LL | #[default]
121146
| ^^^^^^^^^^
122147

123148
error: the `#[default]` attribute may only be used on unit enum variants
124-
--> $DIR/macros-nonfatal-errors.rs:85:5
149+
--> $DIR/macros-nonfatal-errors.rs:91:5
125150
|
126151
LL | Foo {},
127152
| ^^^
128153
|
129154
= help: consider a manual implementation of `Default`
130155

131156
error: default variant must be exhaustive
132-
--> $DIR/macros-nonfatal-errors.rs:93:5
157+
--> $DIR/macros-nonfatal-errors.rs:99:5
133158
|
134159
LL | #[non_exhaustive]
135160
| ----------------- declared `#[non_exhaustive]` here
@@ -139,37 +164,37 @@ LL | Foo,
139164
= help: consider a manual implementation of `Default`
140165

141166
error: asm template must be a string literal
142-
--> $DIR/macros-nonfatal-errors.rs:98:10
167+
--> $DIR/macros-nonfatal-errors.rs:104:10
143168
|
144169
LL | asm!(invalid);
145170
| ^^^^^^^
146171

147172
error: `concat_idents!()` requires ident args
148-
--> $DIR/macros-nonfatal-errors.rs:101:5
173+
--> $DIR/macros-nonfatal-errors.rs:107:5
149174
|
150175
LL | concat_idents!("not", "idents");
151176
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
152177

153178
error: argument must be a string literal
154-
--> $DIR/macros-nonfatal-errors.rs:103:17
179+
--> $DIR/macros-nonfatal-errors.rs:109:17
155180
|
156181
LL | option_env!(invalid);
157182
| ^^^^^^^
158183

159184
error: expected string literal
160-
--> $DIR/macros-nonfatal-errors.rs:104:10
185+
--> $DIR/macros-nonfatal-errors.rs:110:10
161186
|
162187
LL | env!(invalid);
163188
| ^^^^^^^
164189

165190
error: `env!()` takes 1 or 2 arguments
166-
--> $DIR/macros-nonfatal-errors.rs:105:5
191+
--> $DIR/macros-nonfatal-errors.rs:111:5
167192
|
168193
LL | env!(foo, abr, baz);
169194
| ^^^^^^^^^^^^^^^^^^^
170195

171196
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time
172-
--> $DIR/macros-nonfatal-errors.rs:106:5
197+
--> $DIR/macros-nonfatal-errors.rs:112:5
173198
|
174199
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
175200
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -178,7 +203,7 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
178203
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
179204

180205
error: format argument must be a string literal
181-
--> $DIR/macros-nonfatal-errors.rs:108:13
206+
--> $DIR/macros-nonfatal-errors.rs:114:13
182207
|
183208
LL | format!(invalid);
184209
| ^^^^^^^
@@ -189,47 +214,47 @@ LL | format!("{}", invalid);
189214
| +++++
190215

191216
error: argument must be a string literal
192-
--> $DIR/macros-nonfatal-errors.rs:110:14
217+
--> $DIR/macros-nonfatal-errors.rs:116:14
193218
|
194219
LL | include!(invalid);
195220
| ^^^^^^^
196221

197222
error: argument must be a string literal
198-
--> $DIR/macros-nonfatal-errors.rs:112:18
223+
--> $DIR/macros-nonfatal-errors.rs:118:18
199224
|
200225
LL | include_str!(invalid);
201226
| ^^^^^^^
202227

203228
error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
204-
--> $DIR/macros-nonfatal-errors.rs:113:5
229+
--> $DIR/macros-nonfatal-errors.rs:119:5
205230
|
206231
LL | include_str!("i'd be quite surprised if a file with this name existed");
207232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
208233
|
209234
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
210235

211236
error: argument must be a string literal
212-
--> $DIR/macros-nonfatal-errors.rs:114:20
237+
--> $DIR/macros-nonfatal-errors.rs:120:20
213238
|
214239
LL | include_bytes!(invalid);
215240
| ^^^^^^^
216241

217242
error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
218-
--> $DIR/macros-nonfatal-errors.rs:115:5
243+
--> $DIR/macros-nonfatal-errors.rs:121:5
219244
|
220245
LL | include_bytes!("i'd be quite surprised if a file with this name existed");
221246
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
222247
|
223248
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
224249

225250
error: trace_macros! accepts only `true` or `false`
226-
--> $DIR/macros-nonfatal-errors.rs:117:5
251+
--> $DIR/macros-nonfatal-errors.rs:123:5
227252
|
228253
LL | trace_macros!(invalid);
229254
| ^^^^^^^^^^^^^^^^^^^^^^
230255

231256
error: default variant must be exhaustive
232-
--> $DIR/macros-nonfatal-errors.rs:127:9
257+
--> $DIR/macros-nonfatal-errors.rs:133:9
233258
|
234259
LL | #[non_exhaustive]
235260
| ----------------- declared `#[non_exhaustive]` here
@@ -239,10 +264,11 @@ LL | Foo,
239264
= help: consider a manual implementation of `Default`
240265

241266
error: cannot find macro `llvm_asm` in this scope
242-
--> $DIR/macros-nonfatal-errors.rs:99:5
267+
--> $DIR/macros-nonfatal-errors.rs:105:5
243268
|
244269
LL | llvm_asm!(invalid);
245270
| ^^^^^^^^
246271

247-
error: aborting due to 28 previous errors
272+
error: aborting due to 29 previous errors
248273

274+
For more information about this error, try `rustc --explain E0665`.

0 commit comments

Comments
 (0)