@@ -5,8 +5,8 @@ use crate::diagnostics::error::{
55 SessionDiagnosticDeriveError ,
66} ;
77use crate :: diagnostics:: utils:: {
8- option_inner_ty , report_error_if_not_applied_to_span, type_matches_path, Applicability ,
9- FieldInfo , HasFieldMap , SetOnce ,
8+ report_error_if_not_applied_to_span, type_matches_path, Applicability , FieldInfo , FieldInnerTy ,
9+ HasFieldMap , SetOnce ,
1010} ;
1111use proc_macro2:: TokenStream ;
1212use quote:: { format_ident, quote} ;
@@ -353,35 +353,40 @@ impl SessionDiagnosticDeriveBuilder {
353353 info : FieldInfo < ' _ > ,
354354 ) -> Result < TokenStream , SessionDiagnosticDeriveError > {
355355 let field_binding = & info. binding . binding ;
356- let option_ty = option_inner_ty ( & info. ty ) ;
357- let generated_code = self . generate_non_option_field_code (
356+
357+ let inner_ty = FieldInnerTy :: from_type ( & info. ty ) ;
358+ let name = attr. path . segments . last ( ) . unwrap ( ) . ident . to_string ( ) ;
359+ let ( binding, needs_destructure) = match ( name. as_str ( ) , & inner_ty) {
360+ // `primary_span` can accept a `Vec<Span>` so don't destructure that.
361+ ( "primary_span" , FieldInnerTy :: Vec ( _) ) => ( quote ! { #field_binding. clone( ) } , false ) ,
362+ _ => ( quote ! { * #field_binding } , true ) ,
363+ } ;
364+
365+ let generated_code = self . generate_inner_field_code (
358366 attr,
359367 FieldInfo {
360368 vis : info. vis ,
361369 binding : info. binding ,
362- ty : option_ty . unwrap_or ( & info. ty ) ,
370+ ty : inner_ty . inner_type ( ) . unwrap_or ( & info. ty ) ,
363371 span : info. span ,
364372 } ,
373+ binding,
365374 ) ?;
366375
367- if option_ty . is_none ( ) {
368- Ok ( quote ! { # generated_code } )
376+ if needs_destructure {
377+ Ok ( inner_ty . with ( field_binding , generated_code) )
369378 } else {
370- Ok ( quote ! {
371- if let Some ( #field_binding) = #field_binding {
372- #generated_code
373- }
374- } )
379+ Ok ( generated_code)
375380 }
376381 }
377382
378- fn generate_non_option_field_code (
383+ fn generate_inner_field_code (
379384 & mut self ,
380385 attr : & Attribute ,
381386 info : FieldInfo < ' _ > ,
387+ binding : TokenStream ,
382388 ) -> Result < TokenStream , SessionDiagnosticDeriveError > {
383389 let diag = & self . diag ;
384- let field_binding = & info. binding . binding ;
385390
386391 let name = attr. path . segments . last ( ) . unwrap ( ) . ident . to_string ( ) ;
387392 let name = name. as_str ( ) ;
@@ -397,14 +402,14 @@ impl SessionDiagnosticDeriveBuilder {
397402 "primary_span" => {
398403 report_error_if_not_applied_to_span ( attr, & info) ?;
399404 Ok ( quote ! {
400- #diag. set_span( * #field_binding ) ;
405+ #diag. set_span( #binding ) ;
401406 } )
402407 }
403408 "label" | "note" | "help" => {
404409 report_error_if_not_applied_to_span ( attr, & info) ?;
405- Ok ( self . add_subdiagnostic ( field_binding , name, name) )
410+ Ok ( self . add_subdiagnostic ( binding , name, name) )
406411 }
407- "subdiagnostic" => Ok ( quote ! { #diag. subdiagnostic( * #field_binding ) ; } ) ,
412+ "subdiagnostic" => Ok ( quote ! { #diag. subdiagnostic( #binding ) ; } ) ,
408413 _ => throw_invalid_attr ! ( attr, & meta, |diag| {
409414 diag
410415 . help( "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes" )
@@ -413,7 +418,7 @@ impl SessionDiagnosticDeriveBuilder {
413418 Meta :: NameValue ( MetaNameValue { lit : syn:: Lit :: Str ( ref s) , .. } ) => match name {
414419 "label" | "note" | "help" => {
415420 report_error_if_not_applied_to_span ( attr, & info) ?;
416- Ok ( self . add_subdiagnostic ( field_binding , name, & s. value ( ) ) )
421+ Ok ( self . add_subdiagnostic ( binding , name, & s. value ( ) ) )
417422 }
418423 _ => throw_invalid_attr ! ( attr, & meta, |diag| {
419424 diag. help( "only `label`, `note` and `help` are valid field attributes" )
@@ -509,7 +514,7 @@ impl SessionDiagnosticDeriveBuilder {
509514 /// `fluent_attr_identifier`.
510515 fn add_subdiagnostic (
511516 & self ,
512- field_binding : & proc_macro2 :: Ident ,
517+ field_binding : TokenStream ,
513518 kind : & str ,
514519 fluent_attr_identifier : & str ,
515520 ) -> TokenStream {
@@ -520,7 +525,7 @@ impl SessionDiagnosticDeriveBuilder {
520525 let fn_name = format_ident ! ( "span_{}" , kind) ;
521526 quote ! {
522527 #diag. #fn_name(
523- * #field_binding,
528+ #field_binding,
524529 rustc_errors:: DiagnosticMessage :: fluent_attr( #slug, #fluent_attr_identifier)
525530 ) ;
526531 }
0 commit comments