rust-lang/rust · #165573
[tiny] Tweak incorrect `#[default]` errors
compiler/rustc_builtin_macros/src/deriving/default.rs35 + / 7 −
@@ -1,6 +1,6 @@ use core::ops::ControlFlow; -use rustc_ast::visit::{Visitor, visit_opt};+use rustc_ast::visit::{Visitor, WalkItemKind, visit_opt}; use rustc_ast::{self as ast, EnumDef, VariantData, attr}; use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};@@ -241,14 +241,23 @@ fn extract_default_variant<'a>( } else { "" };- let guar =- cx.dcx().emit_err(diagnostics::NonUnitDefault { span: variant.ident.span, post });+ let default = attr::find_by_name(&variant.attrs, kw::Default)+ .expect("`#[default]` was present but it isn't now?");+ let guar = cx.dcx().emit_err(diagnostics::NonUnitDefault {+ span: variant.ident.span,+ default_span: default.span,+ post,+ is_item: Some(()),+ }); return Err(guar); } if let Some(non_exhaustive_attr) = attr::find_by_name(&variant.attrs, sym::non_exhaustive) {+ let default = attr::find_by_name(&variant.attrs, kw::Default)+ .expect("`#[default]` was present but it isn't now?"); let guar = cx.dcx().emit_err(diagnostics::NonExhaustiveDefault { span: variant.ident.span,+ default_span: default.span, non_exhaustive: non_exhaustive_attr.span, }); @@ -298,17 +307,27 @@ struct DetectNonVariantDefaultAttr<'a, 'b> { cx: &'a ExtCtxt<'b>, } -impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {- fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {+impl<'a, 'b> DetectNonVariantDefaultAttr<'a, 'b> {+ fn deny_default(&mut self, span: Span, attr: &'a rustc_ast::Attribute, is_item: bool) { if attr.has_name(kw::Default) {- let post = if self.cx.ecfg.features.default_field_values() {+ let post = if self.cx.ecfg.features.default_field_values() && is_item { " or variants where every field has a default value" } else { "" };- self.cx.dcx().emit_err(diagnostics::NonUnitDefault { span: attr.span, post });+ self.cx.dcx().emit_err(diagnostics::NonUnitDefault {+ span,+ default_span: attr.span,+ post,+ is_item: if is_item { Some(()) } else { None },+ }); }+ }+} +impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {+ fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {+ self.deny_default(attr.span, attr, false); rustc_ast::visit::walk_attribute(self, attr); } fn visit_variant(&mut self, v: &'a rustc_ast::Variant) {@@ -320,6 +339,15 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, ' rustc_ast::visit::walk_attribute(self, attr); } }+ fn visit_item(&mut self, item: &'a rustc_ast::Item) {+ let rustc_ast::Item { attrs, id, kind, vis, span, tokens: _ } = item;+ self.visit_vis(vis);+ for attr in attrs {+ self.deny_default(span.shrink_to_lo(), attr, true);+ rustc_ast::visit::walk_attribute(self, attr);+ }+ rustc_ast::visit::try_visit!(kind.walk(attrs, *span, *id, vis, (), self));+ } } fn has_a_default_variant(item: &ast::Item) -> bool {compiler/rustc_builtin_macros/src/diagnostics.rs6 + / 1 −
@@ -429,18 +429,23 @@ pub(crate) struct MultipleDefaultsSugg { #[derive(Diagnostic)] #[diag("the `#[default]` attribute may only be used on unit enum variants{$post}")]-#[help("consider a manual implementation of `Default`")] pub(crate) struct NonUnitDefault { #[primary_span]+ pub(crate) default_span: Span,+ #[context] pub(crate) span: Span, pub(crate) post: &'static str,+ #[help("consider a manual implementation of `Default`")]+ pub(crate) is_item: Option<()>, } #[derive(Diagnostic)] #[diag("default variant must be exhaustive")] #[help("consider a manual implementation of `Default`")] pub(crate) struct NonExhaustiveDefault { #[primary_span]+ pub(crate) default_span: Span,+ #[context] pub(crate) span: Span, #[label("declared `#[non_exhaustive]` here")] pub(crate) non_exhaustive: Span,tests/ui/feature-gates/feature-gate-default-field-values.rs4 + / 4 −
@@ -11,8 +11,8 @@ pub struct Foo { #[derive(Default)] pub enum Bar {- #[default]- Foo { //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ #[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ Foo { bar: S = S, //~ ERROR default values on fields are experimental baz: i32 = 42 + 3, //~ ERROR default values on fields are experimental }@@ -51,8 +51,8 @@ pub struct Opt { #[derive(Default)] pub enum OptEnum {- #[default]- Variant { //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ #[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ Variant { mandatory: Option<()>, optional: () = (), //~ ERROR default values on fields are experimental }tests/ui/feature-gates/feature-gate-default-field-values.stderr6 + / 4 −
@@ -1,16 +1,18 @@ error: the `#[default]` attribute may only be used on unit enum variants- --> $DIR/feature-gate-default-field-values.rs:15:5+ --> $DIR/feature-gate-default-field-values.rs:14:5 |+LL | #[default]+ | ^^^^^^^^^^ LL | Foo {- | ^^^ | = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants- --> $DIR/feature-gate-default-field-values.rs:55:5+ --> $DIR/feature-gate-default-field-values.rs:54:5 |+LL | #[default]+ | ^^^^^^^^^^ LL | Variant {- | ^^^^^^^ | = help: consider a manual implementation of `Default` tests/ui/macros/macros-nonfatal-errors.rs8 + / 8 −
@@ -71,7 +71,7 @@ enum ExtraDeriveTokens { enum TwoDefaultAttrs { #[default] #[default]- Foo, //~ERROR multiple `#[default]` attributes+ Foo, //~ ERROR multiple `#[default]` attributes Bar, } @@ -81,22 +81,22 @@ enum ManyDefaultAttrs { #[default] #[default] #[default]- Foo, //~ERROR multiple `#[default]` attributes+ Foo, //~ ERROR multiple `#[default]` attributes Bar, } #[derive(Default)] enum DefaultHasFields {- #[default]- Foo {}, //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ #[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ Foo {}, Bar, } #[derive(Default)] enum NonExhaustiveDefault {- #[default]+ #[default] //~ ERROR default variant must be exhaustive #[non_exhaustive]- Foo, //~ ERROR default variant must be exhaustive+ Foo, Bar, } @@ -126,9 +126,9 @@ fn main() { const _: () = { #[derive(Default)] enum NonExhaustiveDefaultGeneric<T> {- #[default]+ #[default] //~ ERROR default variant must be exhaustive #[non_exhaustive]- Foo, //~ ERROR default variant must be exhaustive+ Foo, Bar(T), } tests/ui/macros/macros-nonfatal-errors.stderr11 + / 14 −
@@ -3,22 +3,19 @@ error: the `#[default]` attribute may only be used on unit enum variants | LL | #[default] | ^^^^^^^^^^- |- = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants --> $DIR/macros-nonfatal-errors.rs:18:36 | LL | struct DefaultInnerAttrTupleStruct(#[default] ()); | ^^^^^^^^^^- |- = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants --> $DIR/macros-nonfatal-errors.rs:22:1 | LL | #[default] | ^^^^^^^^^^+LL | struct DefaultOuterAttrStruct {} | = help: consider a manual implementation of `Default` @@ -27,6 +24,7 @@ error: the `#[default]` attribute may only be used on unit enum variants | LL | #[default] | ^^^^^^^^^^+LL | enum DefaultOuterAttrEnum { | = help: consider a manual implementation of `Default` @@ -35,16 +33,12 @@ error: the `#[default]` attribute may only be used on unit enum variants | LL | Foo = #[default] 0, | ^^^^^^^^^^- |- = help: consider a manual implementation of `Default` error: the `#[default]` attribute may only be used on unit enum variants --> $DIR/macros-nonfatal-errors.rs:37:14 | LL | Bar([u8; #[default] 1]), | ^^^^^^^^^^- |- = help: consider a manual implementation of `Default` error[E0665]: `#[derive(Default)]` on enum with no `#[default]` --> $DIR/macros-nonfatal-errors.rs:42:10@@ -142,20 +136,22 @@ LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants- --> $DIR/macros-nonfatal-errors.rs:91:5+ --> $DIR/macros-nonfatal-errors.rs:90:5 |+LL | #[default]+ | ^^^^^^^^^^ LL | Foo {},- | ^^^ | = help: consider a manual implementation of `Default` error: default variant must be exhaustive- --> $DIR/macros-nonfatal-errors.rs:99:5+ --> $DIR/macros-nonfatal-errors.rs:97:5 |+LL | #[default]+ | ^^^^^^^^^^ LL | #[non_exhaustive] | ----------------- declared `#[non_exhaustive]` here LL | Foo,- | ^^^ | = help: consider a manual implementation of `Default` @@ -239,12 +235,13 @@ LL | trace_macros!(invalid); | ^^^^^^^^^^^^^^^^^^^^^^ error: default variant must be exhaustive- --> $DIR/macros-nonfatal-errors.rs:131:9+ --> $DIR/macros-nonfatal-errors.rs:129:9 |+LL | #[default]+ | ^^^^^^^^^^ LL | #[non_exhaustive] | ----------------- declared `#[non_exhaustive]` here LL | Foo,- | ^^^ | = help: consider a manual implementation of `Default` tests/ui/structs/default-field-values-non_exhaustive.rs2 + / 2 −
@@ -19,8 +19,8 @@ enum Enum { enum EnumWithDefault { #[non_exhaustive] //~^ ERROR `#[non_exhaustive]` can't be used to annotate structs with default field values- #[default]- Variant { //~ ERROR default variant must be exhaustive+ #[default] //~ ERROR default variant must be exhaustive+ Variant { field: i32 = 42 + 3, } }tests/ui/structs/default-field-values-non_exhaustive.stderr4 + / 3 −
@@ -1,11 +1,12 @@ error: default variant must be exhaustive- --> $DIR/default-field-values-non_exhaustive.rs:23:5+ --> $DIR/default-field-values-non_exhaustive.rs:22:5 | LL | #[non_exhaustive] | ----------------- declared `#[non_exhaustive]` here-...+LL |+LL | #[default]+ | ^^^^^^^^^^ LL | Variant {- | ^^^^^^^ | = help: consider a manual implementation of `Default` tests/ui/structs/default-field-values/failures.rs2 + / 2 −
@@ -45,8 +45,8 @@ const fn foo() -> i32 { #[derive(Debug, Default)] enum E {- #[default]- Variant {} //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ #[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants+ Variant {} } union Utests/ui/structs/default-field-values/failures.stderr3 + / 2 −
@@ -1,8 +1,9 @@ error: the `#[default]` attribute may only be used on unit enum variants or variants where every field has a default value- --> $DIR/failures.rs:49:5+ --> $DIR/failures.rs:48:5 |+LL | #[default]+ | ^^^^^^^^^^ LL | Variant {}- | ^^^^^^^ | = help: consider a manual implementation of `Default`