@@ -930,6 +930,7 @@ impl<'a> Parser<'a> {
930
930
/// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"]
931
931
/// ```
932
932
fn parse_trait_bound_modifiers ( & mut self ) -> PResult < ' a , TraitBoundModifiers > {
933
+ let modifier_lo = self . token . span ;
933
934
let constness = if self . eat ( & token:: Tilde ) {
934
935
let tilde = self . prev_token . span ;
935
936
self . expect_keyword ( kw:: Const ) ?;
@@ -962,6 +963,7 @@ impl<'a> Parser<'a> {
962
963
} else {
963
964
BoundAsyncness :: Normal
964
965
} ;
966
+ let modifier_hi = self . prev_token . span ;
965
967
966
968
let polarity = if self . eat ( & token:: Question ) {
967
969
BoundPolarity :: Maybe ( self . prev_token . span )
@@ -972,6 +974,33 @@ impl<'a> Parser<'a> {
972
974
BoundPolarity :: Positive
973
975
} ;
974
976
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
+
975
1004
Ok ( TraitBoundModifiers { constness, asyncness, polarity } )
976
1005
}
977
1006
0 commit comments