about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl6
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs13
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0665.md15
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.rs8
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.stderr82
6 files changed, 84 insertions, 53 deletions
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 87d3d288013..7a31d2a2239 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -249,9 +249,9 @@ builtin_macros_naked_functions_testing_attribute =
     .label = function marked with testing attribute here
     .naked_attribute = `#[naked]` is incompatible with testing attributes
 
-builtin_macros_no_default_variant = no default declared
-    .help = make a unit variant default by placing `#[default]` above it
-    .suggestion = make `{$ident}` default
+builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[default]`
+    .label = this enum needs a unit variant marked with `#[default]`
+    .suggestion = make this unit variant default by placing `#[default]` on it
 
 builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi`
 
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index a7d9f608cbd..3c7bebd0f19 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -42,7 +42,9 @@ pub(crate) fn expand_deriving_default(
                     StaticStruct(_, fields) => {
                         default_struct_substructure(cx, trait_span, substr, fields)
                     }
-                    StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def),
+                    StaticEnum(enum_def, _) => {
+                        default_enum_substructure(cx, trait_span, enum_def, item.span())
+                    }
                     _ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"),
                 }
             })),
@@ -96,9 +98,10 @@ fn default_enum_substructure(
     cx: &ExtCtxt<'_>,
     trait_span: Span,
     enum_def: &EnumDef,
+    item_span: Span,
 ) -> BlockOrExpr {
     let expr = match try {
-        let default_variant = extract_default_variant(cx, enum_def, trait_span)?;
+        let default_variant = extract_default_variant(cx, enum_def, trait_span, item_span)?;
         validate_default_attribute(cx, default_variant)?;
         default_variant
     } {
@@ -146,6 +149,7 @@ fn extract_default_variant<'a>(
     cx: &ExtCtxt<'_>,
     enum_def: &'a EnumDef,
     trait_span: Span,
+    item_span: Span,
 ) -> Result<&'a rustc_ast::Variant, ErrorGuaranteed> {
     let default_variants: SmallVec<[_; 1]> = enum_def
         .variants
@@ -163,9 +167,10 @@ fn extract_default_variant<'a>(
                 .filter(|variant| !attr::contains_name(&variant.attrs, sym::non_exhaustive));
 
             let suggs = possible_defaults
-                .map(|v| errors::NoDefaultVariantSugg { span: v.span, ident: v.ident })
+                .map(|v| errors::NoDefaultVariantSugg { span: v.span.shrink_to_lo() })
                 .collect();
-            let guar = cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, suggs });
+            let guar =
+                cx.dcx().emit_err(errors::NoDefaultVariant { span: trait_span, item_span, suggs });
 
             return Err(guar);
         }
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index b3198e7743d..1abdfdb9c65 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -369,26 +369,21 @@ pub(crate) struct DerivePathArgsValue {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_no_default_variant)]
-#[help]
+#[diag(builtin_macros_no_default_variant, code = E0665)]
 pub(crate) struct NoDefaultVariant {
     #[primary_span]
     pub(crate) span: Span,
+    #[label]
+    pub(crate) item_span: Span,
     #[subdiagnostic]
     pub(crate) suggs: Vec<NoDefaultVariantSugg>,
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(
-    builtin_macros_suggestion,
-    code = "#[default] {ident}",
-    applicability = "maybe-incorrect",
-    style = "tool-only"
-)]
+#[suggestion(builtin_macros_suggestion, code = "#[default] ", applicability = "maybe-incorrect")]
 pub(crate) struct NoDefaultVariantSugg {
     #[primary_span]
     pub(crate) span: Span,
-    pub(crate) ident: Ident,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0665.md b/compiler/rustc_error_codes/src/error_codes/E0665.md
index d5fd2130840..caa94423377 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0665.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0665.md
@@ -1,10 +1,9 @@
-#### Note: this error code is no longer emitted by the compiler.
-
-The `Default` trait was derived on an enum.
+The `Default` trait was derived on an enum without specifying the default
+variant.
 
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0665
 #[derive(Default)]
 enum Food {
     Sweet,
@@ -16,8 +15,8 @@ The `Default` cannot be derived on an enum for the simple reason that the
 compiler doesn't know which value to pick by default whereas it can for a
 struct as long as all its fields implement the `Default` trait as well.
 
-For the case where the desired default variant has no data, you can annotate
-it with `#[default]` to derive it:
+For the case where the desired default variant has no payload, you can
+annotate it with `#[default]` to derive it:
 
 ```
 #[derive(Default)]
@@ -28,8 +27,8 @@ enum Food {
 }
 ```
 
-In the case where the default variant does have data, you will have to
-implement `Default` on your enum "by hand":
+In the case where the default variant does have a payload, you will have to
+implement `Default` on your enum manually:
 
 ```
 enum Food {
diff --git a/tests/ui/macros/macros-nonfatal-errors.rs b/tests/ui/macros/macros-nonfatal-errors.rs
index 46e865031ec..658455b1b5b 100644
--- a/tests/ui/macros/macros-nonfatal-errors.rs
+++ b/tests/ui/macros/macros-nonfatal-errors.rs
@@ -39,12 +39,18 @@ enum AttrOnInnerExpression {
     Baz,
 }
 
-#[derive(Default)] //~ ERROR no default declared
+#[derive(Default)] //~ ERROR `#[derive(Default)]` on enum with no `#[default]`
 enum NoDeclaredDefault {
     Foo,
     Bar,
 }
 
+#[derive(Default)] //~ ERROR `#[derive(Default)]` on enum with no `#[default]`
+enum NoDeclaredDefaultWithoutUnitVariant {
+    Foo(i32),
+    Bar(i32),
+}
+
 #[derive(Default)] //~ ERROR multiple declared defaults
 enum MultipleDefaults {
     #[default]
diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr
index abf43e2a009..fd5e41986a8 100644
--- a/tests/ui/macros/macros-nonfatal-errors.stderr
+++ b/tests/ui/macros/macros-nonfatal-errors.stderr
@@ -46,18 +46,43 @@ LL |     Bar([u8; #[default] 1]),
    |
    = help: consider a manual implementation of `Default`
 
-error: no default declared
+error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
   --> $DIR/macros-nonfatal-errors.rs:42:10
    |
-LL | #[derive(Default)]
-   |          ^^^^^^^
+LL |   #[derive(Default)]
+   |            ^^^^^^^
+LL | / enum NoDeclaredDefault {
+LL | |     Foo,
+LL | |     Bar,
+LL | | }
+   | |_- this enum needs a unit variant marked with `#[default]`
    |
-   = help: make a unit variant default by placing `#[default]` above it
    = 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,
+   |     ++++++++++
 
-error: multiple declared defaults
+error[E0665]: `#[derive(Default)]` on enum with no `#[default]`
   --> $DIR/macros-nonfatal-errors.rs:48:10
    |
+LL |   #[derive(Default)]
+   |            ^^^^^^^
+LL | / enum NoDeclaredDefaultWithoutUnitVariant {
+LL | |     Foo(i32),
+LL | |     Bar(i32),
+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)
+
+error: multiple declared defaults
+  --> $DIR/macros-nonfatal-errors.rs:54:10
+   |
 LL | #[derive(Default)]
    |          ^^^^^^^
 ...
@@ -74,7 +99,7 @@ LL |     Baz,
    = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `#[default]` attribute does not accept a value
-  --> $DIR/macros-nonfatal-errors.rs:60:5
+  --> $DIR/macros-nonfatal-errors.rs:66:5
    |
 LL |     #[default = 1]
    |     ^^^^^^^^^^^^^^
@@ -82,7 +107,7 @@ LL |     #[default = 1]
    = help: try using `#[default]`
 
 error: multiple `#[default]` attributes
-  --> $DIR/macros-nonfatal-errors.rs:68:5
+  --> $DIR/macros-nonfatal-errors.rs:74:5
    |
 LL |     #[default]
    |     ---------- `#[default]` used here
@@ -93,13 +118,13 @@ LL |     Foo,
    |
    = note: only one `#[default]` attribute is needed
 help: try removing this
-  --> $DIR/macros-nonfatal-errors.rs:67:5
+  --> $DIR/macros-nonfatal-errors.rs:73:5
    |
 LL |     #[default]
    |     ^^^^^^^^^^
 
 error: multiple `#[default]` attributes
-  --> $DIR/macros-nonfatal-errors.rs:78:5
+  --> $DIR/macros-nonfatal-errors.rs:84:5
    |
 LL |     #[default]
    |     ---------- `#[default]` used here
@@ -111,7 +136,7 @@ LL |     Foo,
    |
    = note: only one `#[default]` attribute is needed
 help: try removing these
-  --> $DIR/macros-nonfatal-errors.rs:75:5
+  --> $DIR/macros-nonfatal-errors.rs:81:5
    |
 LL |     #[default]
    |     ^^^^^^^^^^
@@ -121,7 +146,7 @@ LL |     #[default]
    |     ^^^^^^^^^^
 
 error: the `#[default]` attribute may only be used on unit enum variants
-  --> $DIR/macros-nonfatal-errors.rs:85:5
+  --> $DIR/macros-nonfatal-errors.rs:91:5
    |
 LL |     Foo {},
    |     ^^^
@@ -129,7 +154,7 @@ LL |     Foo {},
    = help: consider a manual implementation of `Default`
 
 error: default variant must be exhaustive
-  --> $DIR/macros-nonfatal-errors.rs:93:5
+  --> $DIR/macros-nonfatal-errors.rs:99:5
    |
 LL |     #[non_exhaustive]
    |     ----------------- declared `#[non_exhaustive]` here
@@ -139,37 +164,37 @@ LL |     Foo,
    = help: consider a manual implementation of `Default`
 
 error: asm template must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:98:10
+  --> $DIR/macros-nonfatal-errors.rs:104:10
    |
 LL |     asm!(invalid);
    |          ^^^^^^^
 
 error: `concat_idents!()` requires ident args
-  --> $DIR/macros-nonfatal-errors.rs:101:5
+  --> $DIR/macros-nonfatal-errors.rs:107:5
    |
 LL |     concat_idents!("not", "idents");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:103:17
+  --> $DIR/macros-nonfatal-errors.rs:109:17
    |
 LL |     option_env!(invalid);
    |                 ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:104:10
+  --> $DIR/macros-nonfatal-errors.rs:110:10
    |
 LL |     env!(invalid);
    |          ^^^^^^^
 
 error: `env!()` takes 1 or 2 arguments
-  --> $DIR/macros-nonfatal-errors.rs:105:5
+  --> $DIR/macros-nonfatal-errors.rs:111:5
    |
 LL |     env!(foo, abr, baz);
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time
-  --> $DIR/macros-nonfatal-errors.rs:106:5
+  --> $DIR/macros-nonfatal-errors.rs:112:5
    |
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -178,7 +203,7 @@ LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: format argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:108:13
+  --> $DIR/macros-nonfatal-errors.rs:114:13
    |
 LL |     format!(invalid);
    |             ^^^^^^^
@@ -189,19 +214,19 @@ LL |     format!("{}", invalid);
    |             +++++
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:110:14
+  --> $DIR/macros-nonfatal-errors.rs:116:14
    |
 LL |     include!(invalid);
    |              ^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:112:18
+  --> $DIR/macros-nonfatal-errors.rs:118:18
    |
 LL |     include_str!(invalid);
    |                  ^^^^^^^
 
 error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
-  --> $DIR/macros-nonfatal-errors.rs:113:5
+  --> $DIR/macros-nonfatal-errors.rs:119:5
    |
 LL |     include_str!("i'd be quite surprised if a file with this name existed");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,13 +234,13 @@ LL |     include_str!("i'd be quite surprised if a file with this name existed")
    = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:114:20
+  --> $DIR/macros-nonfatal-errors.rs:120:20
    |
 LL |     include_bytes!(invalid);
    |                    ^^^^^^^
 
 error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG
-  --> $DIR/macros-nonfatal-errors.rs:115:5
+  --> $DIR/macros-nonfatal-errors.rs:121:5
    |
 LL |     include_bytes!("i'd be quite surprised if a file with this name existed");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -223,13 +248,13 @@ LL |     include_bytes!("i'd be quite surprised if a file with this name existed
    = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: trace_macros! accepts only `true` or `false`
-  --> $DIR/macros-nonfatal-errors.rs:117:5
+  --> $DIR/macros-nonfatal-errors.rs:123:5
    |
 LL |     trace_macros!(invalid);
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: default variant must be exhaustive
-  --> $DIR/macros-nonfatal-errors.rs:127:9
+  --> $DIR/macros-nonfatal-errors.rs:133:9
    |
 LL |         #[non_exhaustive]
    |         ----------------- declared `#[non_exhaustive]` here
@@ -239,10 +264,11 @@ LL |         Foo,
    = help: consider a manual implementation of `Default`
 
 error: cannot find macro `llvm_asm` in this scope
-  --> $DIR/macros-nonfatal-errors.rs:99:5
+  --> $DIR/macros-nonfatal-errors.rs:105:5
    |
 LL |     llvm_asm!(invalid);
    |     ^^^^^^^^
 
-error: aborting due to 28 previous errors
+error: aborting due to 29 previous errors
 
+For more information about this error, try `rustc --explain E0665`.