@@ -15,19 +15,19 @@ use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta
1515use synstructure:: { BindingInfo , Structure , VariantInfo } ;
1616
1717/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
18- pub ( crate ) struct SubdiagnosticDerive < ' a > {
19- structure : Structure < ' a > ,
18+ pub ( crate ) struct SubdiagnosticDeriveBuilder {
2019 diag : syn:: Ident ,
20+ f : syn:: Ident ,
2121}
2222
23- impl < ' a > SubdiagnosticDerive < ' a > {
24- pub ( crate ) fn new ( structure : Structure < ' a > ) -> Self {
23+ impl SubdiagnosticDeriveBuilder {
24+ pub ( crate ) fn new ( ) -> Self {
2525 let diag = format_ident ! ( "diag" ) ;
26- Self { structure, diag }
26+ let f = format_ident ! ( "f" ) ;
27+ Self { diag, f }
2728 }
2829
29- pub ( crate ) fn into_tokens ( self ) -> TokenStream {
30- let SubdiagnosticDerive { mut structure, diag } = self ;
30+ pub ( crate ) fn into_tokens < ' a > ( self , mut structure : Structure < ' a > ) -> TokenStream {
3131 let implementation = {
3232 let ast = structure. ast ( ) ;
3333 let span = ast. span ( ) . unwrap ( ) ;
@@ -53,8 +53,8 @@ impl<'a> SubdiagnosticDerive<'a> {
5353
5454 structure. bind_with ( |_| synstructure:: BindStyle :: Move ) ;
5555 let variants_ = structure. each_variant ( |variant| {
56- let mut builder = SubdiagnosticDeriveBuilder {
57- diag : & diag ,
56+ let mut builder = SubdiagnosticDeriveVariantBuilder {
57+ parent : & self ,
5858 variant,
5959 span,
6060 fields : build_field_mapping ( variant) ,
@@ -72,9 +72,17 @@ impl<'a> SubdiagnosticDerive<'a> {
7272 }
7373 } ;
7474
75+ let diag = & self . diag ;
76+ let f = & self . f ;
7577 let ret = structure. gen_impl ( quote ! {
7678 gen impl rustc_errors:: AddToDiagnostic for @Self {
77- fn add_to_diagnostic( self , #diag: & mut rustc_errors:: Diagnostic ) {
79+ fn add_to_diagnostic_with<__F>( self , #diag: & mut rustc_errors:: Diagnostic , #f: __F)
80+ where
81+ __F: Fn (
82+ & mut rustc_errors:: Diagnostic ,
83+ rustc_errors:: SubdiagnosticMessage
84+ ) -> rustc_errors:: SubdiagnosticMessage ,
85+ {
7886 use rustc_errors:: { Applicability , IntoDiagnosticArg } ;
7987 #implementation
8088 }
@@ -88,9 +96,9 @@ impl<'a> SubdiagnosticDerive<'a> {
8896/// for the final generated method. This is a separate struct to `SubdiagnosticDerive`
8997/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a
9098/// double mut borrow later on.
91- struct SubdiagnosticDeriveBuilder < ' a > {
99+ struct SubdiagnosticDeriveVariantBuilder < ' parent , ' a > {
92100 /// The identifier to use for the generated `DiagnosticBuilder` instance.
93- diag : & ' a syn :: Ident ,
101+ parent : & ' parent SubdiagnosticDeriveBuilder ,
94102
95103 /// Info for the current variant (or the type if not an enum).
96104 variant : & ' a VariantInfo < ' a > ,
@@ -112,7 +120,7 @@ struct SubdiagnosticDeriveBuilder<'a> {
112120 has_suggestion_parts : bool ,
113121}
114122
115- impl < ' a > HasFieldMap for SubdiagnosticDeriveBuilder < ' a > {
123+ impl < ' parent , ' a > HasFieldMap for SubdiagnosticDeriveVariantBuilder < ' parent , ' a > {
116124 fn get_field_binding ( & self , field : & String ) -> Option < & TokenStream > {
117125 self . fields . get ( field)
118126 }
@@ -156,7 +164,7 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
156164 }
157165}
158166
159- impl < ' a > SubdiagnosticDeriveBuilder < ' a > {
167+ impl < ' parent , ' a > SubdiagnosticDeriveVariantBuilder < ' parent , ' a > {
160168 fn identify_kind ( & mut self ) -> Result < Vec < ( SubdiagnosticKind , Path ) > , DiagnosticDeriveError > {
161169 let mut kind_slugs = vec ! [ ] ;
162170
@@ -187,7 +195,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
187195 let ast = binding. ast ( ) ;
188196 assert_eq ! ( ast. attrs. len( ) , 0 , "field with attribute used as diagnostic arg" ) ;
189197
190- let diag = & self . diag ;
198+ let diag = & self . parent . diag ;
191199 let ident = ast. ident . as_ref ( ) . unwrap ( ) ;
192200 // strip `r#` prefix, if present
193201 let ident = format_ident ! ( "{}" , ident) ;
@@ -442,11 +450,14 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
442450
443451 let span_field = self . span_field . value_ref ( ) ;
444452
445- let diag = & self . diag ;
453+ let diag = & self . parent . diag ;
454+ let f = & self . parent . f ;
446455 let mut calls = TokenStream :: new ( ) ;
447456 for ( kind, slug) in kind_slugs {
457+ let message = format_ident ! ( "__message" ) ;
458+ calls. extend ( quote ! { let #message = #f( #diag, rustc_errors:: fluent:: #slug. into( ) ) ; } ) ;
459+
448460 let name = format_ident ! ( "{}{}" , if span_field. is_some( ) { "span_" } else { "" } , kind) ;
449- let message = quote ! { rustc_errors:: fluent:: #slug } ;
450461 let call = match kind {
451462 SubdiagnosticKind :: Suggestion { suggestion_kind, applicability, code } => {
452463 let applicability = applicability
0 commit comments