@@ -5,8 +5,8 @@ use crate::diagnostics::error::{
5
5
SessionDiagnosticDeriveError ,
6
6
} ;
7
7
use 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 ,
10
10
} ;
11
11
use proc_macro2:: TokenStream ;
12
12
use quote:: { format_ident, quote} ;
@@ -353,35 +353,40 @@ impl SessionDiagnosticDeriveBuilder {
353
353
info : FieldInfo < ' _ > ,
354
354
) -> Result < TokenStream , SessionDiagnosticDeriveError > {
355
355
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 (
358
366
attr,
359
367
FieldInfo {
360
368
vis : info. vis ,
361
369
binding : info. binding ,
362
- ty : option_ty . unwrap_or ( & info. ty ) ,
370
+ ty : inner_ty . inner_type ( ) . unwrap_or ( & info. ty ) ,
363
371
span : info. span ,
364
372
} ,
373
+ binding,
365
374
) ?;
366
375
367
- if option_ty . is_none ( ) {
368
- Ok ( quote ! { # generated_code } )
376
+ if needs_destructure {
377
+ Ok ( inner_ty . with ( field_binding , generated_code) )
369
378
} else {
370
- Ok ( quote ! {
371
- if let Some ( #field_binding) = #field_binding {
372
- #generated_code
373
- }
374
- } )
379
+ Ok ( generated_code)
375
380
}
376
381
}
377
382
378
- fn generate_non_option_field_code (
383
+ fn generate_inner_field_code (
379
384
& mut self ,
380
385
attr : & Attribute ,
381
386
info : FieldInfo < ' _ > ,
387
+ binding : TokenStream ,
382
388
) -> Result < TokenStream , SessionDiagnosticDeriveError > {
383
389
let diag = & self . diag ;
384
- let field_binding = & info. binding . binding ;
385
390
386
391
let name = attr. path . segments . last ( ) . unwrap ( ) . ident . to_string ( ) ;
387
392
let name = name. as_str ( ) ;
@@ -397,14 +402,14 @@ impl SessionDiagnosticDeriveBuilder {
397
402
"primary_span" => {
398
403
report_error_if_not_applied_to_span ( attr, & info) ?;
399
404
Ok ( quote ! {
400
- #diag. set_span( * #field_binding ) ;
405
+ #diag. set_span( #binding ) ;
401
406
} )
402
407
}
403
408
"label" | "note" | "help" => {
404
409
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) )
406
411
}
407
- "subdiagnostic" => Ok ( quote ! { #diag. subdiagnostic( * #field_binding ) ; } ) ,
412
+ "subdiagnostic" => Ok ( quote ! { #diag. subdiagnostic( #binding ) ; } ) ,
408
413
_ => throw_invalid_attr ! ( attr, & meta, |diag| {
409
414
diag
410
415
. help( "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes" )
@@ -413,7 +418,7 @@ impl SessionDiagnosticDeriveBuilder {
413
418
Meta :: NameValue ( MetaNameValue { lit : syn:: Lit :: Str ( ref s) , .. } ) => match name {
414
419
"label" | "note" | "help" => {
415
420
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 ( ) ) )
417
422
}
418
423
_ => throw_invalid_attr ! ( attr, & meta, |diag| {
419
424
diag. help( "only `label`, `note` and `help` are valid field attributes" )
@@ -509,7 +514,7 @@ impl SessionDiagnosticDeriveBuilder {
509
514
/// `fluent_attr_identifier`.
510
515
fn add_subdiagnostic (
511
516
& self ,
512
- field_binding : & proc_macro2 :: Ident ,
517
+ field_binding : TokenStream ,
513
518
kind : & str ,
514
519
fluent_attr_identifier : & str ,
515
520
) -> TokenStream {
@@ -520,7 +525,7 @@ impl SessionDiagnosticDeriveBuilder {
520
525
let fn_name = format_ident ! ( "span_{}" , kind) ;
521
526
quote ! {
522
527
#diag. #fn_name(
523
- * #field_binding,
528
+ #field_binding,
524
529
rustc_errors:: DiagnosticMessage :: fluent_attr( #slug, #fluent_attr_identifier)
525
530
) ;
526
531
}
0 commit comments