@@ -12,7 +12,7 @@ use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple};
12
12
use syn:: { MetaList , MetaNameValue , NestedMeta , Path } ;
13
13
use synstructure:: { BindingInfo , VariantInfo } ;
14
14
15
- use super :: error:: invalid_nested_attr;
15
+ use super :: error:: { invalid_attr , invalid_nested_attr} ;
16
16
17
17
thread_local ! {
18
18
pub static CODE_IDENT_COUNT : RefCell <u32 > = RefCell :: new( 0 ) ;
@@ -472,32 +472,42 @@ pub(super) fn build_suggestion_code(
472
472
}
473
473
474
474
/// Possible styles for suggestion subdiagnostics.
475
- #[ derive( Clone , Copy ) ]
475
+ #[ derive( Clone , Copy , PartialEq ) ]
476
476
pub ( super ) enum SuggestionKind {
477
- /// `#[suggestion]`
478
477
Normal ,
479
- /// `#[suggestion_short]`
480
478
Short ,
481
- /// `#[suggestion_hidden]`
482
479
Hidden ,
483
- /// `#[suggestion_verbose]`
484
480
Verbose ,
481
+ ToolOnly ,
485
482
}
486
483
487
484
impl FromStr for SuggestionKind {
488
485
type Err = ( ) ;
489
486
490
487
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
491
488
match s {
492
- "" => Ok ( SuggestionKind :: Normal ) ,
493
- "_short" => Ok ( SuggestionKind :: Short ) ,
494
- "_hidden" => Ok ( SuggestionKind :: Hidden ) ,
495
- "_verbose" => Ok ( SuggestionKind :: Verbose ) ,
489
+ "normal" => Ok ( SuggestionKind :: Normal ) ,
490
+ "short" => Ok ( SuggestionKind :: Short ) ,
491
+ "hidden" => Ok ( SuggestionKind :: Hidden ) ,
492
+ "verbose" => Ok ( SuggestionKind :: Verbose ) ,
493
+ "tool-only" => Ok ( SuggestionKind :: ToolOnly ) ,
496
494
_ => Err ( ( ) ) ,
497
495
}
498
496
}
499
497
}
500
498
499
+ impl fmt:: Display for SuggestionKind {
500
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
501
+ match self {
502
+ SuggestionKind :: Normal => write ! ( f, "normal" ) ,
503
+ SuggestionKind :: Short => write ! ( f, "short" ) ,
504
+ SuggestionKind :: Hidden => write ! ( f, "hidden" ) ,
505
+ SuggestionKind :: Verbose => write ! ( f, "verbose" ) ,
506
+ SuggestionKind :: ToolOnly => write ! ( f, "tool-only" ) ,
507
+ }
508
+ }
509
+ }
510
+
501
511
impl SuggestionKind {
502
512
pub fn to_suggestion_style ( & self ) -> TokenStream {
503
513
match self {
@@ -513,6 +523,19 @@ impl SuggestionKind {
513
523
SuggestionKind :: Verbose => {
514
524
quote ! { rustc_errors:: SuggestionStyle :: ShowAlways }
515
525
}
526
+ SuggestionKind :: ToolOnly => {
527
+ quote ! { rustc_errors:: SuggestionStyle :: CompletelyHidden }
528
+ }
529
+ }
530
+ }
531
+
532
+ fn from_suffix ( s : & str ) -> Option < Self > {
533
+ match s {
534
+ "" => Some ( SuggestionKind :: Normal ) ,
535
+ "_short" => Some ( SuggestionKind :: Short ) ,
536
+ "_hidden" => Some ( SuggestionKind :: Hidden ) ,
537
+ "_verbose" => Some ( SuggestionKind :: Verbose ) ,
538
+ _ => None ,
516
539
}
517
540
}
518
541
}
@@ -565,25 +588,49 @@ impl SubdiagnosticKind {
565
588
let name = name. as_str ( ) ;
566
589
567
590
let meta = attr. parse_meta ( ) ?;
591
+
568
592
let mut kind = match name {
569
593
"label" => SubdiagnosticKind :: Label ,
570
594
"note" => SubdiagnosticKind :: Note ,
571
595
"help" => SubdiagnosticKind :: Help ,
572
596
"warning" => SubdiagnosticKind :: Warn ,
573
597
_ => {
598
+ // Recover old `#[(multipart_)suggestion_*]` syntaxes
599
+ // FIXME(#100717): remove
574
600
if let Some ( suggestion_kind) =
575
- name. strip_prefix ( "suggestion" ) . and_then ( |s| s . parse ( ) . ok ( ) )
601
+ name. strip_prefix ( "suggestion" ) . and_then ( SuggestionKind :: from_suffix )
576
602
{
603
+ if suggestion_kind != SuggestionKind :: Normal {
604
+ invalid_attr ( attr, & meta)
605
+ . help ( format ! (
606
+ r#"Use `#[suggestion(..., style = "{}")]` instead"# ,
607
+ suggestion_kind
608
+ ) )
609
+ . emit ( ) ;
610
+ }
611
+
577
612
SubdiagnosticKind :: Suggestion {
578
- suggestion_kind,
613
+ suggestion_kind : SuggestionKind :: Normal ,
579
614
applicability : None ,
580
615
code_field : new_code_ident ( ) ,
581
616
code_init : TokenStream :: new ( ) ,
582
617
}
583
618
} else if let Some ( suggestion_kind) =
584
- name. strip_prefix ( "multipart_suggestion" ) . and_then ( |s| s . parse ( ) . ok ( ) )
619
+ name. strip_prefix ( "multipart_suggestion" ) . and_then ( SuggestionKind :: from_suffix )
585
620
{
586
- SubdiagnosticKind :: MultipartSuggestion { suggestion_kind, applicability : None }
621
+ if suggestion_kind != SuggestionKind :: Normal {
622
+ invalid_attr ( attr, & meta)
623
+ . help ( format ! (
624
+ r#"Use `#[multipart_suggestion(..., style = "{}")]` instead"# ,
625
+ suggestion_kind
626
+ ) )
627
+ . emit ( ) ;
628
+ }
629
+
630
+ SubdiagnosticKind :: MultipartSuggestion {
631
+ suggestion_kind : SuggestionKind :: Normal ,
632
+ applicability : None ,
633
+ }
587
634
} else {
588
635
throw_invalid_attr ! ( attr, & meta) ;
589
636
}
@@ -621,6 +668,7 @@ impl SubdiagnosticKind {
621
668
} ;
622
669
623
670
let mut code = None ;
671
+ let mut suggestion_kind = None ;
624
672
625
673
let mut nested_iter = nested. into_iter ( ) . peekable ( ) ;
626
674
@@ -682,16 +730,37 @@ impl SubdiagnosticKind {
682
730
} ) ;
683
731
applicability. set_once ( value, span) ;
684
732
}
733
+ (
734
+ "style" ,
735
+ SubdiagnosticKind :: Suggestion { .. }
736
+ | SubdiagnosticKind :: MultipartSuggestion { .. } ,
737
+ ) => {
738
+ let Some ( value) = string_value else {
739
+ invalid_nested_attr ( attr, & nested_attr) . emit ( ) ;
740
+ continue ;
741
+ } ;
742
+
743
+ let value = value. value ( ) . parse ( ) . unwrap_or_else ( |( ) | {
744
+ span_err ( value. span ( ) . unwrap ( ) , "invalid suggestion style" )
745
+ . help ( "valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`" )
746
+ . emit ( ) ;
747
+ SuggestionKind :: Normal
748
+ } ) ;
749
+
750
+ suggestion_kind. set_once ( value, span) ;
751
+ }
685
752
686
753
// Invalid nested attribute
687
754
( _, SubdiagnosticKind :: Suggestion { .. } ) => {
688
755
invalid_nested_attr ( attr, & nested_attr)
689
- . help ( "only `code` and `applicability` are valid nested attributes" )
756
+ . help (
757
+ "only `style`, `code` and `applicability` are valid nested attributes" ,
758
+ )
690
759
. emit ( ) ;
691
760
}
692
761
( _, SubdiagnosticKind :: MultipartSuggestion { .. } ) => {
693
762
invalid_nested_attr ( attr, & nested_attr)
694
- . help ( "only `applicability` is a valid nested attributes" )
763
+ . help ( "only `style` and `applicability` are valid nested attributes" )
695
764
. emit ( )
696
765
}
697
766
_ => {
@@ -701,19 +770,34 @@ impl SubdiagnosticKind {
701
770
}
702
771
703
772
match kind {
704
- SubdiagnosticKind :: Suggestion { ref code_field, ref mut code_init, .. } => {
773
+ SubdiagnosticKind :: Suggestion {
774
+ ref code_field,
775
+ ref mut code_init,
776
+ suggestion_kind : ref mut kind_field,
777
+ ..
778
+ } => {
779
+ if let Some ( kind) = suggestion_kind. value ( ) {
780
+ * kind_field = kind;
781
+ }
782
+
705
783
* code_init = if let Some ( init) = code. value ( ) {
706
784
init
707
785
} else {
708
786
span_err ( span, "suggestion without `code = \" ...\" `" ) . emit ( ) ;
709
787
quote ! { let #code_field = std:: iter:: empty( ) ; }
710
788
} ;
711
789
}
790
+ SubdiagnosticKind :: MultipartSuggestion {
791
+ suggestion_kind : ref mut kind_field, ..
792
+ } => {
793
+ if let Some ( kind) = suggestion_kind. value ( ) {
794
+ * kind_field = kind;
795
+ }
796
+ }
712
797
SubdiagnosticKind :: Label
713
798
| SubdiagnosticKind :: Note
714
799
| SubdiagnosticKind :: Help
715
- | SubdiagnosticKind :: Warn
716
- | SubdiagnosticKind :: MultipartSuggestion { .. } => { }
800
+ | SubdiagnosticKind :: Warn => { }
717
801
}
718
802
719
803
Ok ( Some ( ( kind, slug) ) )
0 commit comments