@@ -930,6 +930,7 @@ impl<'a> Parser<'a> {
930930 /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"]
931931 /// ```
932932 fn parse_trait_bound_modifiers ( & mut self ) -> PResult < ' a , TraitBoundModifiers > {
933+ let modifier_lo = self . token . span ;
933934 let constness = if self . eat ( & token:: Tilde ) {
934935 let tilde = self . prev_token . span ;
935936 self . expect_keyword ( kw:: Const ) ?;
@@ -962,6 +963,7 @@ impl<'a> Parser<'a> {
962963 } else {
963964 BoundAsyncness :: Normal
964965 } ;
966+ let modifier_hi = self . prev_token . span ;
965967
966968 let polarity = if self . eat ( & token:: Question ) {
967969 BoundPolarity :: Maybe ( self . prev_token . span )
@@ -972,6 +974,33 @@ impl<'a> Parser<'a> {
972974 BoundPolarity :: Positive
973975 } ;
974976
977+ // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.
978+ match polarity {
979+ BoundPolarity :: Positive => {
980+ // All trait bound modifiers allowed to combine with positive polarity
981+ }
982+ BoundPolarity :: Maybe ( polarity_span) | BoundPolarity :: Negative ( polarity_span) => {
983+ match ( asyncness, constness) {
984+ ( BoundAsyncness :: Normal , BoundConstness :: Never ) => {
985+ // Ok, no modifiers.
986+ }
987+ ( _, _) => {
988+ let constness = constness. as_str ( ) ;
989+ let asyncness = asyncness. as_str ( ) ;
990+ let glue =
991+ if !constness. is_empty ( ) && !asyncness. is_empty ( ) { " " } else { "" } ;
992+ let modifiers_concatenated = format ! ( "{constness}{glue}{asyncness}" ) ;
993+ self . dcx ( ) . emit_err ( errors:: PolarityAndModifiers {
994+ polarity_span,
995+ polarity : polarity. as_str ( ) ,
996+ modifiers_span : modifier_lo. to ( modifier_hi) ,
997+ modifiers_concatenated,
998+ } ) ;
999+ }
1000+ }
1001+ }
1002+ }
1003+
9751004 Ok ( TraitBoundModifiers { constness, asyncness, polarity } )
9761005 }
9771006
0 commit comments