@@ -71,6 +71,7 @@ impl SubdiagnosticDerive {
71
71
span_field : None ,
72
72
applicability : None ,
73
73
has_suggestion_parts : false ,
74
+ has_subdiagnostic : false ,
74
75
is_enum,
75
76
} ;
76
77
builder. into_tokens ( ) . unwrap_or_else ( |v| v. to_compile_error ( ) )
@@ -133,6 +134,10 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
133
134
/// during finalization if still `false`.
134
135
has_suggestion_parts : bool ,
135
136
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
+
136
141
/// Set to true when this variant is an enum variant rather than just the body of a struct.
137
142
is_enum : bool ,
138
143
}
@@ -373,6 +378,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
373
378
374
379
Ok ( quote ! { } )
375
380
}
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
+ }
376
388
_ => {
377
389
let mut span_attrs = vec ! [ ] ;
378
390
if kind_stats. has_multipart_suggestion {
@@ -480,18 +492,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
480
492
481
493
pub ( crate ) fn into_tokens ( & mut self ) -> Result < TokenStream , DiagnosticDeriveError > {
482
494
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
- } ;
495
495
496
496
let kind_stats: KindsStatistics =
497
497
kind_slugs. iter ( ) . map ( |( kind, _slug, _no_span) | kind) . collect ( ) ;
@@ -510,6 +510,19 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
510
510
. map ( |binding| self . generate_field_attr_code ( binding, kind_stats) )
511
511
. collect ( ) ;
512
512
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
+
513
526
let span_field = self . span_field . value_ref ( ) ;
514
527
515
528
let diag = & self . parent . diag ;
0 commit comments