Disallow #[default] Variant {}
regardless of feature flag
This commit is contained in:
parent
148a77dfde
commit
2d6e763cc6
5 changed files with 38 additions and 11 deletions
|
@ -261,7 +261,7 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive
|
||||||
|
|
||||||
builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters
|
builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters
|
||||||
|
|
||||||
builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
|
builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants{$post}
|
||||||
.help = consider a manual implementation of `Default`
|
.help = consider a manual implementation of `Default`
|
||||||
|
|
||||||
builtin_macros_only_one_argument = {$name} takes 1 argument
|
builtin_macros_only_one_argument = {$name} takes 1 argument
|
||||||
|
|
|
@ -199,10 +199,17 @@ fn extract_default_variant<'a>(
|
||||||
if cx.ecfg.features.default_field_values()
|
if cx.ecfg.features.default_field_values()
|
||||||
&& let VariantData::Struct { fields, .. } = &variant.data
|
&& let VariantData::Struct { fields, .. } = &variant.data
|
||||||
&& fields.iter().all(|f| f.default.is_some())
|
&& fields.iter().all(|f| f.default.is_some())
|
||||||
|
// Disallow `#[default] Variant {}`
|
||||||
|
&& !fields.is_empty()
|
||||||
{
|
{
|
||||||
// Allowed
|
// Allowed
|
||||||
} else if !matches!(variant.data, VariantData::Unit(..)) {
|
} else if !matches!(variant.data, VariantData::Unit(..)) {
|
||||||
let guar = cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span });
|
let post = if cx.ecfg.features.default_field_values() {
|
||||||
|
" or variants where every field has a default value"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
let guar = cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span, post });
|
||||||
return Err(guar);
|
return Err(guar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +268,12 @@ struct DetectNonVariantDefaultAttr<'a, 'b> {
|
||||||
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
|
impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
|
||||||
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
|
fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
|
||||||
if attr.has_name(kw::Default) {
|
if attr.has_name(kw::Default) {
|
||||||
self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span });
|
let post = if self.cx.ecfg.features.default_field_values() {
|
||||||
|
" or variants where every field has a default value"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span, post });
|
||||||
}
|
}
|
||||||
|
|
||||||
rustc_ast::visit::walk_attribute(self, attr);
|
rustc_ast::visit::walk_attribute(self, attr);
|
||||||
|
|
|
@ -424,6 +424,7 @@ pub(crate) struct MultipleDefaultsSugg {
|
||||||
pub(crate) struct NonUnitDefault {
|
pub(crate) struct NonUnitDefault {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub(crate) span: Span,
|
pub(crate) span: Span,
|
||||||
|
pub(crate) post: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -41,6 +41,12 @@ const fn foo() -> i32 {
|
||||||
42
|
42
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
enum E {
|
||||||
|
#[default]
|
||||||
|
Variant {} //~ ERROR the `#[default]` attribute may only be used on unit enum variants
|
||||||
|
}
|
||||||
|
|
||||||
fn main () {
|
fn main () {
|
||||||
let _ = Foo { .. }; // ok
|
let _ = Foo { .. }; // ok
|
||||||
let _ = Foo::default(); // ok
|
let _ = Foo::default(); // ok
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
error: the `#[default]` attribute may only be used on unit enum variants or variants where every field has a default value
|
||||||
|
--> $DIR/default-field-values-failures.rs:47:5
|
||||||
|
|
|
||||||
|
LL | Variant {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider a manual implementation of `Default`
|
||||||
|
|
||||||
error: generic parameters may not be used in const operations
|
error: generic parameters may not be used in const operations
|
||||||
--> $DIR/default-field-values-failures.rs:22:23
|
--> $DIR/default-field-values-failures.rs:22:23
|
||||||
|
|
|
|
||||||
|
@ -30,13 +38,13 @@ LL | pub struct S;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: missing mandatory field `bar`
|
error: missing mandatory field `bar`
|
||||||
--> $DIR/default-field-values-failures.rs:47:21
|
--> $DIR/default-field-values-failures.rs:53:21
|
||||||
|
|
|
|
||||||
LL | let _ = Bar { .. };
|
LL | let _ = Bar { .. };
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/default-field-values-failures.rs:51:17
|
--> $DIR/default-field-values-failures.rs:57:17
|
||||||
|
|
|
|
||||||
LL | let _ = Rak(..);
|
LL | let _ = Rak(..);
|
||||||
| --- ^^ expected `i32`, found `RangeFull`
|
| --- ^^ expected `i32`, found `RangeFull`
|
||||||
|
@ -49,19 +57,19 @@ note: tuple struct defined here
|
||||||
LL | pub struct Rak(i32 = 42);
|
LL | pub struct Rak(i32 = 42);
|
||||||
| ^^^
|
| ^^^
|
||||||
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
|
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
|
||||||
--> $DIR/default-field-values-failures.rs:51:17
|
--> $DIR/default-field-values-failures.rs:57:17
|
||||||
|
|
|
|
||||||
LL | let _ = Rak(..);
|
LL | let _ = Rak(..);
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
|
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
|
||||||
--> $DIR/default-field-values-failures.rs:53:13
|
--> $DIR/default-field-values-failures.rs:59:13
|
||||||
|
|
|
|
||||||
LL | let _ = Rak(0, ..);
|
LL | let _ = Rak(0, ..);
|
||||||
| ^^^ -- unexpected argument #2 of type `RangeFull`
|
| ^^^ -- unexpected argument #2 of type `RangeFull`
|
||||||
|
|
|
|
||||||
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
|
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
|
||||||
--> $DIR/default-field-values-failures.rs:53:20
|
--> $DIR/default-field-values-failures.rs:59:20
|
||||||
|
|
|
|
||||||
LL | let _ = Rak(0, ..);
|
LL | let _ = Rak(0, ..);
|
||||||
| ^^
|
| ^^
|
||||||
|
@ -77,13 +85,13 @@ LL + let _ = Rak(0);
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
|
error[E0061]: this struct takes 1 argument but 2 arguments were supplied
|
||||||
--> $DIR/default-field-values-failures.rs:55:13
|
--> $DIR/default-field-values-failures.rs:61:13
|
||||||
|
|
|
|
||||||
LL | let _ = Rak(.., 0);
|
LL | let _ = Rak(.., 0);
|
||||||
| ^^^ -- unexpected argument #1 of type `RangeFull`
|
| ^^^ -- unexpected argument #1 of type `RangeFull`
|
||||||
|
|
|
|
||||||
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
|
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
|
||||||
--> $DIR/default-field-values-failures.rs:55:17
|
--> $DIR/default-field-values-failures.rs:61:17
|
||||||
|
|
|
|
||||||
LL | let _ = Rak(.., 0);
|
LL | let _ = Rak(.., 0);
|
||||||
| ^^
|
| ^^
|
||||||
|
@ -104,7 +112,7 @@ error: generic `Self` types are currently not permitted in anonymous constants
|
||||||
LL | bar: S = Self::S,
|
LL | bar: S = Self::S,
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0061, E0277, E0308.
|
Some errors have detailed explanations: E0061, E0277, E0308.
|
||||||
For more information about an error, try `rustc --explain E0061`.
|
For more information about an error, try `rustc --explain E0061`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue