Skip to content

Commit 2d6e763

Browse files
committed
Disallow #[default] Variant {} regardless of feature flag
1 parent 148a77d commit 2d6e763

File tree

5 files changed

+38
-11
lines changed

5 files changed

+38
-11
lines changed

Diff for: compiler/rustc_builtin_macros/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive
261261
262262
builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters
263263
264-
builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
264+
builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants{$post}
265265
.help = consider a manual implementation of `Default`
266266
267267
builtin_macros_only_one_argument = {$name} takes 1 argument

Diff for: compiler/rustc_builtin_macros/src/deriving/default.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,17 @@ fn extract_default_variant<'a>(
199199
if cx.ecfg.features.default_field_values()
200200
&& let VariantData::Struct { fields, .. } = &variant.data
201201
&& fields.iter().all(|f| f.default.is_some())
202+
// Disallow `#[default] Variant {}`
203+
&& !fields.is_empty()
202204
{
203205
// Allowed
204206
} else if !matches!(variant.data, VariantData::Unit(..)) {
205-
let guar = cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span });
207+
let post = if cx.ecfg.features.default_field_values() {
208+
" or variants where every field has a default value"
209+
} else {
210+
""
211+
};
212+
let guar = cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span, post });
206213
return Err(guar);
207214
}
208215

@@ -261,7 +268,12 @@ struct DetectNonVariantDefaultAttr<'a, 'b> {
261268
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
262269
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
263270
if attr.has_name(kw::Default) {
264-
self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span });
271+
let post = if self.cx.ecfg.features.default_field_values() {
272+
" or variants where every field has a default value"
273+
} else {
274+
""
275+
};
276+
self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span, post });
265277
}
266278

267279
rustc_ast::visit::walk_attribute(self, attr);

Diff for: compiler/rustc_builtin_macros/src/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ pub(crate) struct MultipleDefaultsSugg {
424424
pub(crate) struct NonUnitDefault {
425425
#[primary_span]
426426
pub(crate) span: Span,
427+
pub(crate) post: &'static str,
427428
}
428429

429430
#[derive(Diagnostic)]

Diff for: tests/ui/structs/default-field-values-failures.rs

+6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ const fn foo() -> i32 {
4141
42
4242
}
4343

44+
#[derive(Debug, Default)]
45+
enum E {
46+
#[default]
47+
Variant {} //~ ERROR the `#[default]` attribute may only be used on unit enum variants
48+
}
49+
4450
fn main () {
4551
let _ = Foo { .. }; // ok
4652
let _ = Foo::default(); // ok

Diff for: tests/ui/structs/default-field-values-failures.stderr

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
error: the `#[default]` attribute may only be used on unit enum variants or variants where every field has a default value
2+
--> $DIR/default-field-values-failures.rs:47:5
3+
|
4+
LL | Variant {}
5+
| ^^^^^^^
6+
|
7+
= help: consider a manual implementation of `Default`
8+
19
error: generic parameters may not be used in const operations
210
--> $DIR/default-field-values-failures.rs:22:23
311
|
@@ -30,13 +38,13 @@ LL | pub struct S;
3038
|
3139

3240
error: missing mandatory field `bar`
33-
--> $DIR/default-field-values-failures.rs:47:21
41+
--> $DIR/default-field-values-failures.rs:53:21
3442
|
3543
LL | let _ = Bar { .. };
3644
| ^
3745

3846
error[E0308]: mismatched types
39-
--> $DIR/default-field-values-failures.rs:51:17
47+
--> $DIR/default-field-values-failures.rs:57:17
4048
|
4149
LL | let _ = Rak(..);
4250
| --- ^^ expected `i32`, found `RangeFull`
@@ -49,19 +57,19 @@ note: tuple struct defined here
4957
LL | pub struct Rak(i32 = 42);
5058
| ^^^
5159
help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
52-
--> $DIR/default-field-values-failures.rs:51:17
60+
--> $DIR/default-field-values-failures.rs:57:17
5361
|
5462
LL | let _ = Rak(..);
5563
| ^^
5664

5765
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
58-
--> $DIR/default-field-values-failures.rs:53:13
66+
--> $DIR/default-field-values-failures.rs:59:13
5967
|
6068
LL | let _ = Rak(0, ..);
6169
| ^^^ -- unexpected argument #2 of type `RangeFull`
6270
|
6371
help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
64-
--> $DIR/default-field-values-failures.rs:53:20
72+
--> $DIR/default-field-values-failures.rs:59:20
6573
|
6674
LL | let _ = Rak(0, ..);
6775
| ^^
@@ -77,13 +85,13 @@ LL + let _ = Rak(0);
7785
|
7886

7987
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
80-
--> $DIR/default-field-values-failures.rs:55:13
88+
--> $DIR/default-field-values-failures.rs:61:13
8189
|
8290
LL | let _ = Rak(.., 0);
8391
| ^^^ -- unexpected argument #1 of type `RangeFull`
8492
|
8593
help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
86-
--> $DIR/default-field-values-failures.rs:55:17
94+
--> $DIR/default-field-values-failures.rs:61:17
8795
|
8896
LL | let _ = Rak(.., 0);
8997
| ^^
@@ -104,7 +112,7 @@ error: generic `Self` types are currently not permitted in anonymous constants
104112
LL | bar: S = Self::S,
105113
| ^^^^
106114

107-
error: aborting due to 8 previous errors
115+
error: aborting due to 9 previous errors
108116

109117
Some errors have detailed explanations: E0061, E0277, E0308.
110118
For more information about an error, try `rustc --explain E0061`.

0 commit comments

Comments
 (0)