diff options
| author | Xiretza <xiretza@xiretza.xyz> | 2024-04-20 12:52:05 +0000 |
|---|---|---|
| committer | Xiretza <xiretza@xiretza.xyz> | 2024-04-21 07:45:03 +0000 |
| commit | c88bb6c011a034a8b29d2a61734de0d36a02a1e9 (patch) | |
| tree | 1142ecaf1e28ba7e32ee55d07b8cd42b1cfea1df /compiler/rustc_macros/src | |
| parent | 5646b65cf58123679fdf4ef489f690d1b21e1436 (diff) | |
| download | rust-c88bb6c011a034a8b29d2a61734de0d36a02a1e9.tar.gz rust-c88bb6c011a034a8b29d2a61734de0d36a02a1e9.zip | |
Allow nesting subdiagnostics
Diffstat (limited to 'compiler/rustc_macros/src')
| -rw-r--r-- | compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/lib.rs | 1 |
2 files changed, 26 insertions, 12 deletions
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 94914266884..45236771bce 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -71,6 +71,7 @@ impl SubdiagnosticDerive { span_field: None, applicability: None, has_suggestion_parts: false, + has_subdiagnostic: false, is_enum, }; builder.into_tokens().unwrap_or_else(|v| v.to_compile_error()) @@ -133,6 +134,10 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> { /// during finalization if still `false`. has_suggestion_parts: bool, + /// Set to true when a `#[subdiagnostic]` field is encountered, used to suppress the error + /// emitted when no subdiagnostic kinds are specified on the variant itself. + has_subdiagnostic: bool, + /// Set to true when this variant is an enum variant rather than just the body of a struct. is_enum: bool, } @@ -373,6 +378,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { Ok(quote! {}) } + "subdiagnostic" => { + let f = &self.parent.f; + let diag = &self.parent.diag; + let binding = &info.binding; + self.has_subdiagnostic = true; + Ok(quote! { #binding.add_to_diag_with(#diag, #f); }) + } _ => { let mut span_attrs = vec![]; if kind_stats.has_multipart_suggestion { @@ -480,18 +492,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> { let kind_slugs = self.identify_kind()?; - if kind_slugs.is_empty() { - 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, _no_span)| kind).collect(); @@ -510,6 +510,19 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); + if kind_slugs.is_empty() { + if self.is_enum { + // It's okay for a variant to not be a subdiagnostic at all.. + return Ok(quote! {}); + } else if !self.has_subdiagnostic { + // ..but structs should always be _something_. + throw_span_err!( + self.variant.ast().ident.span().unwrap(), + "subdiagnostic kind not specified" + ); + } + }; + let span_field = self.span_field.value_ref(); let diag = &self.parent.diag; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index eedc508fb14..c7b7eadbd9d 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -144,6 +144,7 @@ decl_derive!( help, note, warning, + subdiagnostic, suggestion, suggestion_short, suggestion_hidden, |
