@@ -594,29 +594,108 @@ pub(crate) struct AttributeParseError<'a> {
594594 pub ( crate ) suggestions : Vec < String > ,
595595}
596596
597+ impl < ' a > AttributeParseError < ' a > {
598+ fn render_expected_specific_argument < G > (
599+ & self ,
600+ diag : & mut Diag < ' _ , G > ,
601+ possibilities : & [ Symbol ] ,
602+ strings : bool ,
603+ ) where
604+ G : EmissionGuarantee ,
605+ {
606+ let quote = if strings { '"' } else { '`' } ;
607+ match possibilities {
608+ & [ ] => { }
609+ & [ x] => {
610+ diag. span_label (
611+ self . span ,
612+ format ! ( "the only valid argument here is {quote}{x}{quote}" ) ,
613+ ) ;
614+ }
615+ [ first, second] => {
616+ diag. span_label (
617+ self . span ,
618+ format ! ( "valid arguments are {quote}{first}{quote} or {quote}{second}{quote}" ) ,
619+ ) ;
620+ }
621+ [ first @ .., second_to_last, last] => {
622+ let mut res = String :: new ( ) ;
623+ for i in first {
624+ res. push_str ( & format ! ( "{quote}{i}{quote}, " ) ) ;
625+ }
626+ res. push_str ( & format ! ( "{quote}{second_to_last}{quote} or {quote}{last}{quote}" ) ) ;
627+
628+ diag. span_label ( self . span , format ! ( "valid arguments are {res}" ) ) ;
629+ }
630+ }
631+ }
632+
633+ fn render_expected_specific_argument_list < G > (
634+ & self ,
635+ diag : & mut Diag < ' _ , G > ,
636+ possibilities : & [ Symbol ] ,
637+ strings : bool ,
638+ ) where
639+ G : EmissionGuarantee ,
640+ {
641+ let description = self . description ( ) ;
642+
643+ let quote = if strings { '"' } else { '`' } ;
644+ match possibilities {
645+ & [ ] => { }
646+ & [ x] => {
647+ diag. span_label (
648+ self . span ,
649+ format ! (
650+ "this {description} is only valid with {quote}{x}{quote} as an argument"
651+ ) ,
652+ ) ;
653+ }
654+ [ first, second] => {
655+ diag. span_label ( self . span , format ! ( "this {description} is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument" ) ) ;
656+ }
657+ [ first @ .., second_to_last, last] => {
658+ let mut res = String :: new ( ) ;
659+ for i in first {
660+ res. push_str ( & format ! ( "{quote}{i}{quote}, " ) ) ;
661+ }
662+ res. push_str ( & format ! ( "{quote}{second_to_last}{quote} or {quote}{last}{quote}" ) ) ;
663+
664+ diag. span_label ( self . span , format ! ( "this {description} is only valid with one of the following arguments: {res}" ) ) ;
665+ }
666+ }
667+ }
668+
669+ fn description ( & self ) -> & ' static str {
670+ match self . description {
671+ ParsedDescription :: Attribute => "attribute" ,
672+ ParsedDescription :: Macro => "macro" ,
673+ }
674+ }
675+ }
676+
597677impl < ' a , G : EmissionGuarantee > Diagnostic < ' a , G > for AttributeParseError < ' _ > {
598678 fn into_diag ( self , dcx : DiagCtxtHandle < ' a > , level : Level ) -> Diag < ' a , G > {
599679 let name = self . path . to_string ( ) ;
600680
601- let description = match self . description {
602- ParsedDescription :: Attribute => "attribute" ,
603- ParsedDescription :: Macro => "macro" ,
604- } ;
681+ let description = self . description ( ) ;
605682
606683 let mut diag = Diag :: new ( dcx, level, format ! ( "malformed `{name}` {description} input" ) ) ;
607684 diag. span ( self . attr_span ) ;
608685 diag. code ( E0539 ) ;
609- match self . reason {
686+ match & self . reason {
610687 AttributeParseErrorReason :: ExpectedStringLiteral { byte_string } => {
611688 if let Some ( start_point_span) = byte_string {
612689 diag. span_suggestion (
613- start_point_span,
690+ * start_point_span,
614691 "consider removing the prefix" ,
615692 "" ,
616693 Applicability :: MaybeIncorrect ,
617694 ) ;
618695 diag. note ( "expected a normal string literal, not a byte string literal" ) ;
619696
697+ // Avoid emitting an "attribute must be of the form" suggestion, as the
698+ // attribute is likely to be well-formed already.
620699 return diag;
621700 } else {
622701 diag. span_label ( self . span , "expected a string literal here" ) ;
@@ -693,62 +772,14 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
693772 strings,
694773 list : false ,
695774 } => {
696- let quote = if strings { '"' } else { '`' } ;
697- match possibilities {
698- & [ ] => { }
699- & [ x] => {
700- diag. span_label (
701- self . span ,
702- format ! ( "the only valid argument here is {quote}{x}{quote}" ) ,
703- ) ;
704- }
705- [ first, second] => {
706- diag. span_label ( self . span , format ! ( "valid arguments are {quote}{first}{quote} or {quote}{second}{quote}" ) ) ;
707- }
708- [ first @ .., second_to_last, last] => {
709- let mut res = String :: new ( ) ;
710- for i in first {
711- res. push_str ( & format ! ( "{quote}{i}{quote}, " ) ) ;
712- }
713- res. push_str ( & format ! (
714- "{quote}{second_to_last}{quote} or {quote}{last}{quote}"
715- ) ) ;
716-
717- diag. span_label ( self . span , format ! ( "valid arguments are {res}" ) ) ;
718- }
719- }
775+ self . render_expected_specific_argument ( & mut diag, * possibilities, * strings) ;
720776 }
721777 AttributeParseErrorReason :: ExpectedSpecificArgument {
722778 possibilities,
723779 strings,
724780 list : true ,
725781 } => {
726- let quote = if strings { '"' } else { '`' } ;
727- match possibilities {
728- & [ ] => { }
729- & [ x] => {
730- diag. span_label (
731- self . span ,
732- format ! (
733- "this {description} is only valid with {quote}{x}{quote} as an argument"
734- ) ,
735- ) ;
736- }
737- [ first, second] => {
738- diag. span_label ( self . span , format ! ( "this {description} is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument" ) ) ;
739- }
740- [ first @ .., second_to_last, last] => {
741- let mut res = String :: new ( ) ;
742- for i in first {
743- res. push_str ( & format ! ( "{quote}{i}{quote}, " ) ) ;
744- }
745- res. push_str ( & format ! (
746- "{quote}{second_to_last}{quote} or {quote}{last}{quote}"
747- ) ) ;
748-
749- diag. span_label ( self . span , format ! ( "this {description} is only valid with one of the following arguments: {res}" ) ) ;
750- }
751- }
782+ self . render_expected_specific_argument_list ( & mut diag, * possibilities, * strings) ;
752783 }
753784 AttributeParseErrorReason :: ExpectedIdentifier => {
754785 diag. span_label ( self . span , "expected a valid identifier here" ) ;
0 commit comments