about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david.wood@huawei.com>2022-10-14 11:09:52 +0100
committerDavid Wood <david.wood@huawei.com>2022-10-17 09:54:24 +0100
commit1045e69e7331734d59ac85391443db9bd29fd2be (patch)
treefe3af45456b877dbdf4225a9ebd308b364d56c5e
parent7fbaf2769634ac1800449a6d2d818615cef7eace (diff)
downloadrust-1045e69e7331734d59ac85391443db9bd29fd2be.tar.gz
rust-1045e69e7331734d59ac85391443db9bd29fd2be.zip
macros: allow subdiagnostic-kind-less variants
Sometimes it is convenient to return a subdiagnostic enum where one or
more of the variants don't add anything to the diagnostic.

Signed-off-by: David Wood <david.wood@huawei.com>
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs21
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs1
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr92
3 files changed, 59 insertions, 55 deletions
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 4fe02e81607..0b82cb5097e 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -41,7 +41,8 @@ impl SubdiagnosticDeriveBuilder {
                 }
             }
 
-            if matches!(ast.data, syn::Data::Enum(..)) {
+            let is_enum = matches!(ast.data, syn::Data::Enum(..));
+            if is_enum {
                 for attr in &ast.attrs {
                     // Always allow documentation comments.
                     if is_doc_comment(attr) {
@@ -67,6 +68,7 @@ impl SubdiagnosticDeriveBuilder {
                     span_field: None,
                     applicability: None,
                     has_suggestion_parts: false,
+                    is_enum,
                 };
                 builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
             });
@@ -127,6 +129,9 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
     /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
     /// during finalization if still `false`.
     has_suggestion_parts: bool,
+
+    /// Set to true when this variant is an enum variant rather than just the body of a struct.
+    is_enum: bool,
 }
 
 impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
@@ -457,10 +462,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
     pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
         let kind_slugs = self.identify_kind()?;
         if kind_slugs.is_empty() {
-            throw_span_err!(
-                self.variant.ast().ident.span().unwrap(),
-                "subdiagnostic kind not specified"
-            );
+            if self.is_enum {
+                // It's okay for a variant to not be a subdiagnostic at all..
+                return Ok(quote! {});
+            } else {
+                // ..but structs should always be _something_.
+                throw_span_err!(
+                    self.variant.ast().ident.span().unwrap(),
+                    "subdiagnostic kind not specified"
+                );
+            }
         };
 
         let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 31aae7ba12d..2fe93d46d0a 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -237,7 +237,6 @@ enum V {
         var: String,
     },
     B {
-    //~^ ERROR subdiagnostic kind not specified
         #[primary_span]
         span: Span,
         var: String,
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 171b89e657d..1173d24248b 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -134,20 +134,14 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
 LL |     #[label(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:239:5
-   |
-LL |     B {
-   |     ^
-
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:251:5
+  --> $DIR/subdiagnostic-derive.rs:250:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: label without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:248:1
+  --> $DIR/subdiagnostic-derive.rs:247:1
    |
 LL | / #[label(parser::add_paren)]
 LL | |
@@ -159,13 +153,13 @@ LL | | }
    | |_^
 
 error: `#[applicability]` is only valid on suggestions
-  --> $DIR/subdiagnostic-derive.rs:261:5
+  --> $DIR/subdiagnostic-derive.rs:260:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:271:5
+  --> $DIR/subdiagnostic-derive.rs:270:5
    |
 LL |     #[bar]
    |     ^^^^^^
@@ -173,13 +167,13 @@ LL |     #[bar]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:282:5
+  --> $DIR/subdiagnostic-derive.rs:281:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:293:5
+  --> $DIR/subdiagnostic-derive.rs:292:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
@@ -187,7 +181,7 @@ LL |     #[bar("...")]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: unexpected unsupported untagged union
-  --> $DIR/subdiagnostic-derive.rs:309:1
+  --> $DIR/subdiagnostic-derive.rs:308:1
    |
 LL | / union AC {
 LL | |
@@ -197,7 +191,7 @@ LL | | }
    | |_^
 
 error: `#[label(parser::add_paren)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:324:28
+  --> $DIR/subdiagnostic-derive.rs:323:28
    |
 LL | #[label(parser::add_paren, parser::add_paren)]
    |                            ^^^^^^^^^^^^^^^^^
@@ -205,67 +199,67 @@ LL | #[label(parser::add_paren, parser::add_paren)]
    = help: a diagnostic slug must be the first argument to the attribute
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:337:5
+  --> $DIR/subdiagnostic-derive.rs:336:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:334:5
+  --> $DIR/subdiagnostic-derive.rs:333:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:343:8
+  --> $DIR/subdiagnostic-derive.rs:342:8
    |
 LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:380:47
+  --> $DIR/subdiagnostic-derive.rs:379:47
    |
 LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
    |                                               ^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:380:33
+  --> $DIR/subdiagnostic-derive.rs:379:33
    |
 LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
    |                                 ^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:398:5
+  --> $DIR/subdiagnostic-derive.rs:397:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:395:5
+  --> $DIR/subdiagnostic-derive.rs:394:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
-  --> $DIR/subdiagnostic-derive.rs:408:5
+  --> $DIR/subdiagnostic-derive.rs:407:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:421:1
+  --> $DIR/subdiagnostic-derive.rs:420:1
    |
 LL | #[suggestion(parser::add_paren)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:431:46
+  --> $DIR/subdiagnostic-derive.rs:430:46
    |
 LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
    |                                              ^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:449:1
+  --> $DIR/subdiagnostic-derive.rs:448:1
    |
 LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
@@ -275,25 +269,25 @@ LL | | }
    | |_^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:463:1
+  --> $DIR/subdiagnostic-derive.rs:462:1
    |
 LL | #[label]
    | ^^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:483:39
+  --> $DIR/subdiagnostic-derive.rs:482:39
    |
 LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
    |                                       ^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:502:43
+  --> $DIR/subdiagnostic-derive.rs:501:43
    |
 LL |     #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
    |                                           ^^^^^^^
 
 error: `#[suggestion_part]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:525:5
+  --> $DIR/subdiagnostic-derive.rs:524:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
@@ -301,7 +295,7 @@ LL |     #[suggestion_part]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
 
 error: `#[suggestion_part(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:528:5
+  --> $DIR/subdiagnostic-derive.rs:527:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -309,7 +303,7 @@ LL |     #[suggestion_part(code = "...")]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:522:1
+  --> $DIR/subdiagnostic-derive.rs:521:1
    |
 LL | / #[suggestion(parser::add_paren, code = "...")]
 LL | |
@@ -321,7 +315,7 @@ LL | | }
    | |_^
 
 error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:537:43
+  --> $DIR/subdiagnostic-derive.rs:536:43
    |
 LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
    |                                           ^^^^^^^^^^^^
@@ -329,7 +323,7 @@ LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "ma
    = help: only `applicability` is a valid nested attributes
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:537:1
+  --> $DIR/subdiagnostic-derive.rs:536:1
    |
 LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
 LL | |
@@ -340,19 +334,19 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:547:5
+  --> $DIR/subdiagnostic-derive.rs:546:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:555:5
+  --> $DIR/subdiagnostic-derive.rs:554:5
    |
 LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:564:5
+  --> $DIR/subdiagnostic-derive.rs:563:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -360,7 +354,7 @@ LL |     #[primary_span]
    = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:561:1
+  --> $DIR/subdiagnostic-derive.rs:560:1
    |
 LL | / #[multipart_suggestion(parser::add_paren)]
 LL | |
@@ -372,19 +366,19 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:572:5
+  --> $DIR/subdiagnostic-derive.rs:571:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:575:5
+  --> $DIR/subdiagnostic-derive.rs:574:5
    |
 LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_part(foo = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:578:23
+  --> $DIR/subdiagnostic-derive.rs:577:23
    |
 LL |     #[suggestion_part(foo = "bar")]
    |                       ^^^^^^^^^^^
@@ -392,31 +386,31 @@ LL |     #[suggestion_part(foo = "bar")]
    = help: `code` is the only valid nested attribute
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:581:5
+  --> $DIR/subdiagnostic-derive.rs:580:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:584:5
+  --> $DIR/subdiagnostic-derive.rs:583:5
    |
 LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:592:37
+  --> $DIR/subdiagnostic-derive.rs:591:37
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
    |                                     ^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:592:23
+  --> $DIR/subdiagnostic-derive.rs:591:23
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
    |                       ^^^^^^^^^^^^
 
 error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
-  --> $DIR/subdiagnostic-derive.rs:621:5
+  --> $DIR/subdiagnostic-derive.rs:620:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
@@ -458,19 +452,19 @@ LL |     #[bar("...")]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:271:7
+  --> $DIR/subdiagnostic-derive.rs:270:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:282:7
+  --> $DIR/subdiagnostic-derive.rs:281:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:293:7
+  --> $DIR/subdiagnostic-derive.rs:292:7
    |
 LL |     #[bar("...")]
    |       ^^^
@@ -481,6 +475,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
 LL | #[label(slug)]
    |         ^^^^ not found in `rustc_errors::fluent`
 
-error: aborting due to 68 previous errors
+error: aborting due to 67 previous errors
 
 For more information about this error, try `rustc --explain E0425`.