@@ -71,6 +71,7 @@ impl SubdiagnosticDerive {
7171 span_field : None ,
7272 applicability : None ,
7373 has_suggestion_parts : false ,
74+ has_subdiagnostic : false ,
7475 is_enum,
7576 } ;
7677 builder. into_tokens ( ) . unwrap_or_else ( |v| v. to_compile_error ( ) )
@@ -133,6 +134,10 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
133134 /// during finalization if still `false`.
134135 has_suggestion_parts : bool ,
135136
137+ /// Set to true when a `#[subdiagnostic]` field is encountered, used to suppress the error
138+ /// emitted when no subdiagnostic kinds are specified on the variant itself.
139+ has_subdiagnostic : bool ,
140+
136141 /// Set to true when this variant is an enum variant rather than just the body of a struct.
137142 is_enum : bool ,
138143}
@@ -373,6 +378,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
373378
374379 Ok ( quote ! { } )
375380 }
381+ "subdiagnostic" => {
382+ let f = & self . parent . f ;
383+ let diag = & self . parent . diag ;
384+ let binding = & info. binding ;
385+ self . has_subdiagnostic = true ;
386+ Ok ( quote ! { #binding. add_to_diag_with( #diag, #f) ; } )
387+ }
376388 _ => {
377389 let mut span_attrs = vec ! [ ] ;
378390 if kind_stats. has_multipart_suggestion {
@@ -480,18 +492,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
480492
481493 pub ( crate ) fn into_tokens ( & mut self ) -> Result < TokenStream , DiagnosticDeriveError > {
482494 let kind_slugs = self . identify_kind ( ) ?;
483- if kind_slugs. is_empty ( ) {
484- if self . is_enum {
485- // It's okay for a variant to not be a subdiagnostic at all..
486- return Ok ( quote ! { } ) ;
487- } else {
488- // ..but structs should always be _something_.
489- throw_span_err ! (
490- self . variant. ast( ) . ident. span( ) . unwrap( ) ,
491- "subdiagnostic kind not specified"
492- ) ;
493- }
494- } ;
495495
496496 let kind_stats: KindsStatistics =
497497 kind_slugs. iter ( ) . map ( |( kind, _slug, _no_span) | kind) . collect ( ) ;
@@ -510,6 +510,19 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
510510 . map ( |binding| self . generate_field_attr_code ( binding, kind_stats) )
511511 . collect ( ) ;
512512
513+ if kind_slugs. is_empty ( ) {
514+ if self . is_enum {
515+ // It's okay for a variant to not be a subdiagnostic at all..
516+ return Ok ( quote ! { } ) ;
517+ } else if !self . has_subdiagnostic {
518+ // ..but structs should always be _something_.
519+ throw_span_err ! (
520+ self . variant. ast( ) . ident. span( ) . unwrap( ) ,
521+ "subdiagnostic kind not specified"
522+ ) ;
523+ }
524+ } ;
525+
513526 let span_field = self . span_field . value_ref ( ) ;
514527
515528 let diag = & self . parent . diag ;
0 commit comments