@@ -935,9 +935,14 @@ impl<'a> Parser<'a> {
935
935
/// If no modifiers are present, this does not consume any tokens.
936
936
///
937
937
/// ```ebnf
938
- /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"]
938
+ /// CONSTNESS = [["~"] "const"]
939
+ /// ASYNCNESS = ["async"]
940
+ /// POLARITY = ["?" | "!"]
939
941
/// ```
942
+ ///
943
+ /// See `parse_generic_ty_bound` for the complete grammar of trait bound modifiers.
940
944
fn parse_trait_bound_modifiers ( & mut self ) -> PResult < ' a , TraitBoundModifiers > {
945
+ let modifier_lo = self . token . span ;
941
946
let constness = if self . eat ( & token:: Tilde ) {
942
947
let tilde = self . prev_token . span ;
943
948
self . expect_keyword ( kw:: Const ) ?;
@@ -970,6 +975,7 @@ impl<'a> Parser<'a> {
970
975
} else {
971
976
BoundAsyncness :: Normal
972
977
} ;
978
+ let modifier_hi = self . prev_token . span ;
973
979
974
980
let polarity = if self . eat ( & token:: Question ) {
975
981
BoundPolarity :: Maybe ( self . prev_token . span )
@@ -980,13 +986,40 @@ impl<'a> Parser<'a> {
980
986
BoundPolarity :: Positive
981
987
} ;
982
988
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
+
983
1016
Ok ( TraitBoundModifiers { constness, asyncness, polarity } )
984
1017
}
985
1018
986
1019
/// Parses a type bound according to:
987
1020
/// ```ebnf
988
1021
/// 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
990
1023
/// ```
991
1024
///
992
1025
/// For example, this grammar accepts `for<'a: 'b> ~const ?m::Trait<'a>`.
@@ -996,16 +1029,37 @@ impl<'a> Parser<'a> {
996
1029
has_parens : bool ,
997
1030
leading_token : & Token ,
998
1031
) -> PResult < ' a , GenericBound > {
999
- let modifiers = self . parse_trait_bound_modifiers ( ) ?;
1000
1032
let ( mut lifetime_defs, binder_span) = self . parse_late_bound_lifetime_defs ( ) ?;
1001
1033
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
+
1002
1051
// Recover erroneous lifetime bound with modifiers or binder.
1003
1052
// e.g. `T: for<'a> 'a` or `T: ~const 'a`.
1004
1053
if self . token . is_lifetime ( ) {
1005
1054
let _: ErrorGuaranteed = self . error_lt_bound_with_modifiers ( modifiers, binder_span) ;
1006
1055
return self . parse_generic_lt_bound ( lo, has_parens) ;
1007
1056
}
1008
1057
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
+
1009
1063
let mut path = if self . token . is_keyword ( kw:: Fn )
1010
1064
&& self . look_ahead ( 1 , |tok| tok. kind == TokenKind :: OpenDelim ( Delimiter :: Parenthesis ) )
1011
1065
&& let Some ( path) = self . recover_path_from_fn ( )
0 commit comments