@@ -430,74 +430,8 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
430
430
| suggestion_kind @ "suggestion_short"
431
431
| suggestion_kind @ "suggestion_hidden"
432
432
| suggestion_kind @ "suggestion_verbose" => {
433
- // For suggest, we need to ensure we are running on a (Span,
434
- // Applicability) pair.
435
- let ( span, applicability) = ( || match & info. ty {
436
- ty @ syn:: Type :: Path ( ..)
437
- if type_matches_path ( ty, & [ "rustc_span" , "Span" ] ) =>
438
- {
439
- let binding = & info. binding . binding ;
440
- Ok ( (
441
- quote ! ( * #binding) ,
442
- quote ! ( rustc_errors:: Applicability :: Unspecified ) ,
443
- ) )
444
- }
445
- syn:: Type :: Tuple ( tup) => {
446
- let mut span_idx = None ;
447
- let mut applicability_idx = None ;
448
- for ( idx, elem) in tup. elems . iter ( ) . enumerate ( ) {
449
- if type_matches_path ( elem, & [ "rustc_span" , "Span" ] ) {
450
- if span_idx. is_none ( ) {
451
- span_idx = Some ( syn:: Index :: from ( idx) ) ;
452
- } else {
453
- throw_span_err ! (
454
- info. span. unwrap( ) ,
455
- "type of field annotated with `#[suggestion(...)]` contains more than one Span"
456
- ) ;
457
- }
458
- } else if type_matches_path (
459
- elem,
460
- & [ "rustc_errors" , "Applicability" ] ,
461
- ) {
462
- if applicability_idx. is_none ( ) {
463
- applicability_idx = Some ( syn:: Index :: from ( idx) ) ;
464
- } else {
465
- throw_span_err ! (
466
- info. span. unwrap( ) ,
467
- "type of field annotated with `#[suggestion(...)]` contains more than one Applicability"
468
- ) ;
469
- }
470
- }
471
- }
472
- if let Some ( span_idx) = span_idx {
473
- let binding = & info. binding . binding ;
474
- let span = quote ! ( #binding. #span_idx) ;
475
- let applicability = applicability_idx
476
- . map (
477
- |applicability_idx| quote ! ( #binding. #applicability_idx) ,
478
- )
479
- . unwrap_or_else ( || {
480
- quote ! ( rustc_errors:: Applicability :: Unspecified )
481
- } ) ;
482
- return Ok ( ( span, applicability) ) ;
483
- }
484
- throw_span_err ! (
485
- info. span. unwrap( ) ,
486
- "wrong types for suggestion" ,
487
- |diag| {
488
- diag. help( "#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)" )
489
- }
490
- ) ;
491
- }
492
- _ => throw_span_err ! (
493
- info. span. unwrap( ) ,
494
- "wrong field type for suggestion" ,
495
- |diag| {
496
- diag. help( "#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)" )
497
- }
498
- ) ,
499
- } ) ( ) ?;
500
- // Now read the key-value pairs.
433
+ let ( span, applicability) = self . span_and_applicability_of_ty ( info) ?;
434
+
501
435
let mut msg = None ;
502
436
let mut code = None ;
503
437
@@ -562,6 +496,65 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
562
496
} )
563
497
}
564
498
499
+ fn span_and_applicability_of_ty (
500
+ & self ,
501
+ info : FieldInfo < ' _ > ,
502
+ ) -> Result < ( proc_macro2:: TokenStream , proc_macro2:: TokenStream ) , SessionDiagnosticDeriveError >
503
+ {
504
+ match & info. ty {
505
+ // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`.
506
+ ty @ syn:: Type :: Path ( ..) if type_matches_path ( ty, & [ "rustc_span" , "Span" ] ) => {
507
+ let binding = & info. binding . binding ;
508
+ Ok ( ( quote ! ( * #binding) , quote ! ( rustc_errors:: Applicability :: Unspecified ) ) )
509
+ }
510
+ // If `ty` is `(Span, Applicability)` then return tokens accessing those.
511
+ syn:: Type :: Tuple ( tup) => {
512
+ let mut span_idx = None ;
513
+ let mut applicability_idx = None ;
514
+
515
+ for ( idx, elem) in tup. elems . iter ( ) . enumerate ( ) {
516
+ if type_matches_path ( elem, & [ "rustc_span" , "Span" ] ) {
517
+ if span_idx. is_none ( ) {
518
+ span_idx = Some ( syn:: Index :: from ( idx) ) ;
519
+ } else {
520
+ throw_span_err ! (
521
+ info. span. unwrap( ) ,
522
+ "type of field annotated with `#[suggestion(...)]` contains more than one Span"
523
+ ) ;
524
+ }
525
+ } else if type_matches_path ( elem, & [ "rustc_errors" , "Applicability" ] ) {
526
+ if applicability_idx. is_none ( ) {
527
+ applicability_idx = Some ( syn:: Index :: from ( idx) ) ;
528
+ } else {
529
+ throw_span_err ! (
530
+ info. span. unwrap( ) ,
531
+ "type of field annotated with `#[suggestion(...)]` contains more than one Applicability"
532
+ ) ;
533
+ }
534
+ }
535
+ }
536
+
537
+ if let Some ( span_idx) = span_idx {
538
+ let binding = & info. binding . binding ;
539
+ let span = quote ! ( #binding. #span_idx) ;
540
+ let applicability = applicability_idx
541
+ . map ( |applicability_idx| quote ! ( #binding. #applicability_idx) )
542
+ . unwrap_or_else ( || quote ! ( rustc_errors:: Applicability :: Unspecified ) ) ;
543
+
544
+ return Ok ( ( span, applicability) ) ;
545
+ }
546
+
547
+ throw_span_err ! ( info. span. unwrap( ) , "wrong types for suggestion" , |diag| {
548
+ diag. help( "#[suggestion(...)] on a tuple field must be applied to fields of type `(Span, Applicability)`" )
549
+ } ) ;
550
+ }
551
+ // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error.
552
+ _ => throw_span_err ! ( info. span. unwrap( ) , "wrong field type for suggestion" , |diag| {
553
+ diag. help( "#[suggestion(...)] should be applied to fields of type `Span` or `(Span, Applicability)`" )
554
+ } ) ,
555
+ }
556
+ }
557
+
565
558
/// In the strings in the attributes supplied to this macro, we want callers to be able to
566
559
/// reference fields in the format string. For example:
567
560
///
0 commit comments