rust-lang/rust · #165573

[tiny] Tweak incorrect `#[default]` errors

estebank · merged Nov 8, 202610 files · 81 + / 47 −
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 U
tests/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`