about summary refs log tree commit diff
path: root/compiler
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 /compiler
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>
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs21
1 files changed, 16 insertions, 5 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();