@@ -935,9 +935,14 @@ impl<'a> Parser<'a> {
935935     /// If no modifiers are present, this does not consume any tokens. 
936936     /// 
937937     /// ```ebnf 
938-      /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"] 
938+      /// CONSTNESS = [["~"] "const"] 
939+      /// ASYNCNESS = ["async"] 
940+      /// POLARITY = ["?" | "!"] 
939941     /// ``` 
942+      /// 
943+      /// See `parse_generic_ty_bound` for the complete grammar of trait bound modifiers. 
940944     fn  parse_trait_bound_modifiers ( & mut  self )  -> PResult < ' a ,  TraitBoundModifiers >  { 
945+         let  modifier_lo = self . token . span ; 
941946        let  constness = if  self . eat ( & token:: Tilde )  { 
942947            let  tilde = self . prev_token . span ; 
943948            self . expect_keyword ( kw:: Const ) ?; 
@@ -970,6 +975,7 @@ impl<'a> Parser<'a> {
970975        }  else  { 
971976            BoundAsyncness :: Normal 
972977        } ; 
978+         let  modifier_hi = self . prev_token . span ; 
973979
974980        let  polarity = if  self . eat ( & token:: Question )  { 
975981            BoundPolarity :: Maybe ( self . prev_token . span ) 
@@ -980,13 +986,40 @@ impl<'a> Parser<'a> {
980986            BoundPolarity :: Positive 
981987        } ; 
982988
989+         // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`. 
990+         match  polarity { 
991+             BoundPolarity :: Positive  => { 
992+                 // All trait bound modifiers allowed to combine with positive polarity 
993+             } 
994+             BoundPolarity :: Maybe ( polarity_span)  | BoundPolarity :: Negative ( polarity_span)  => { 
995+                 match  ( asyncness,  constness)  { 
996+                     ( BoundAsyncness :: Normal ,  BoundConstness :: Never )  => { 
997+                         // Ok, no modifiers. 
998+                     } 
999+                     ( _,  _)  => { 
1000+                         let  constness = constness. as_str ( ) ; 
1001+                         let  asyncness = asyncness. as_str ( ) ; 
1002+                         let  glue =
1003+                             if  !constness. is_empty ( )  && !asyncness. is_empty ( )  {  " "  }  else  {  ""  } ; 
1004+                         let  modifiers_concatenated = format ! ( "{constness}{glue}{asyncness}" ) ; 
1005+                         self . dcx ( ) . emit_err ( errors:: PolarityAndModifiers  { 
1006+                             polarity_span, 
1007+                             polarity :  polarity. as_str ( ) , 
1008+                             modifiers_span :  modifier_lo. to ( modifier_hi) , 
1009+                             modifiers_concatenated, 
1010+                         } ) ; 
1011+                     } 
1012+                 } 
1013+             } 
1014+         } 
1015+ 
9831016        Ok ( TraitBoundModifiers  {  constness,  asyncness,  polarity } ) 
9841017    } 
9851018
9861019    /// Parses a type bound according to: 
9871020     /// ```ebnf 
9881021     /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) 
989-      /// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [ for<LT_PARAM_DEFS> ] SIMPLE_PATH 
1022+      /// TY_BOUND_NOPAREN = [for<GENERIC_PARAMS> CONSTNESS ASYNCNESS | POLARITY ] SIMPLE_PATH 
9901023     /// ``` 
9911024     /// 
9921025     /// For example, this grammar accepts `for<'a: 'b> ~const ?m::Trait<'a>`. 
@@ -996,16 +1029,37 @@ impl<'a> Parser<'a> {
9961029        has_parens :  bool , 
9971030        leading_token :  & Token , 
9981031    )  -> PResult < ' a ,  GenericBound >  { 
999-         let  modifiers = self . parse_trait_bound_modifiers ( ) ?; 
10001032        let  ( mut  lifetime_defs,  binder_span)  = self . parse_late_bound_lifetime_defs ( ) ?; 
10011033
1034+         let  modifiers_lo = self . token . span ; 
1035+         let  modifiers = self . parse_trait_bound_modifiers ( ) ?; 
1036+         let  modifiers_span = modifiers_lo. to ( self . prev_token . span ) ; 
1037+ 
1038+         if  let  Some ( binder_span)  = binder_span { 
1039+             match  modifiers. polarity  { 
1040+                 BoundPolarity :: Negative ( polarity_span)  | BoundPolarity :: Maybe ( polarity_span)  => { 
1041+                     self . dcx ( ) . emit_err ( errors:: BinderAndPolarity  { 
1042+                         binder_span, 
1043+                         polarity_span, 
1044+                         polarity :  modifiers. polarity . as_str ( ) , 
1045+                     } ) ; 
1046+                 } 
1047+                 BoundPolarity :: Positive  => { } 
1048+             } 
1049+         } 
1050+ 
10021051        // Recover erroneous lifetime bound with modifiers or binder. 
10031052        // e.g. `T: for<'a> 'a` or `T: ~const 'a`. 
10041053        if  self . token . is_lifetime ( )  { 
10051054            let  _:  ErrorGuaranteed  = self . error_lt_bound_with_modifiers ( modifiers,  binder_span) ; 
10061055            return  self . parse_generic_lt_bound ( lo,  has_parens) ; 
10071056        } 
10081057
1058+         if  let  ( more_lifetime_defs,  Some ( binder_span) )  = self . parse_late_bound_lifetime_defs ( ) ? { 
1059+             lifetime_defs. extend ( more_lifetime_defs) ; 
1060+             self . dcx ( ) . emit_err ( errors:: BinderBeforeModifiers  {  binder_span,  modifiers_span } ) ; 
1061+         } 
1062+ 
10091063        let  mut  path = if  self . token . is_keyword ( kw:: Fn ) 
10101064            && self . look_ahead ( 1 ,  |tok| tok. kind  == TokenKind :: OpenDelim ( Delimiter :: Parenthesis ) ) 
10111065            && let  Some ( path)  = self . recover_path_from_fn ( ) 
0 commit comments