@@ -152,6 +152,7 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
152
152
enum PrevTokenKind {
153
153
DocComment ,
154
154
Comma ,
155
+ Plus ,
155
156
Interpolated ,
156
157
Eof ,
157
158
Other ,
@@ -1061,6 +1062,7 @@ impl<'a> Parser<'a> {
1061
1062
self . prev_token_kind = match self . token {
1062
1063
token:: DocComment ( ..) => PrevTokenKind :: DocComment ,
1063
1064
token:: Comma => PrevTokenKind :: Comma ,
1065
+ token:: BinOp ( token:: Plus ) => PrevTokenKind :: Plus ,
1064
1066
token:: Interpolated ( ..) => PrevTokenKind :: Interpolated ,
1065
1067
token:: Eof => PrevTokenKind :: Eof ,
1066
1068
_ => PrevTokenKind :: Other ,
@@ -1354,20 +1356,29 @@ impl<'a> Parser<'a> {
1354
1356
break ;
1355
1357
}
1356
1358
}
1359
+ let trailing_plus = self . prev_token_kind == PrevTokenKind :: Plus ;
1357
1360
self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
1358
1361
1359
1362
if ts. len ( ) == 1 && !last_comma {
1360
1363
let ty = ts. into_iter ( ) . nth ( 0 ) . unwrap ( ) . unwrap ( ) ;
1364
+ let maybe_bounds = allow_plus && self . token == token:: BinOp ( token:: Plus ) ;
1361
1365
match ty. node {
1362
- // Accept `(Trait1) + Trait2 + 'a` for backward compatibility (#39318).
1363
- TyKind :: Path ( None , ref path)
1364
- if allow_plus && self . token == token:: BinOp ( token:: Plus ) => {
1366
+ // `(TY_BOUND_NOPAREN) + BOUND + ...`.
1367
+ TyKind :: Path ( None , ref path) if maybe_bounds => {
1365
1368
self . bump ( ) ; // `+`
1366
1369
let pt = PolyTraitRef :: new ( Vec :: new ( ) , path. clone ( ) , lo. to ( self . prev_span ) ) ;
1367
1370
let mut bounds = vec ! [ TraitTyParamBound ( pt, TraitBoundModifier :: None ) ] ;
1368
1371
bounds. append ( & mut self . parse_ty_param_bounds ( ) ?) ;
1369
1372
TyKind :: TraitObject ( bounds)
1370
1373
}
1374
+ TyKind :: TraitObject ( ref bounds)
1375
+ if maybe_bounds && bounds. len ( ) == 1 && !trailing_plus => {
1376
+ self . bump ( ) ; // `+`
1377
+ let mut bounds = bounds. clone ( ) ;
1378
+ bounds. append ( & mut self . parse_ty_param_bounds ( ) ?) ;
1379
+ TyKind :: TraitObject ( bounds)
1380
+ }
1381
+ // `(TYPE)`
1371
1382
_ => TyKind :: Paren ( P ( ty) )
1372
1383
}
1373
1384
} else {
@@ -4070,17 +4081,24 @@ impl<'a> Parser<'a> {
4070
4081
// Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
4071
4082
// BOUND = TY_BOUND | LT_BOUND
4072
4083
// LT_BOUND = LIFETIME (e.g. `'a`)
4073
- // TY_BOUND = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`)
4084
+ // TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
4085
+ // TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`)
4074
4086
fn parse_ty_param_bounds_common ( & mut self , allow_plus : bool ) -> PResult < ' a , TyParamBounds > {
4075
4087
let mut bounds = Vec :: new ( ) ;
4076
4088
loop {
4089
+ let has_parens = self . eat ( & token:: OpenDelim ( token:: Paren ) ) ;
4077
4090
let question = if self . eat ( & token:: Question ) { Some ( self . prev_span ) } else { None } ;
4078
4091
if self . check_lifetime ( ) {
4079
4092
if let Some ( question_span) = question {
4080
4093
self . span_err ( question_span,
4081
4094
"`?` may only modify trait bounds, not lifetime bounds" ) ;
4082
4095
}
4083
4096
bounds. push ( RegionTyParamBound ( self . expect_lifetime ( ) ) ) ;
4097
+ if has_parens {
4098
+ self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
4099
+ self . span_err ( self . prev_span ,
4100
+ "parenthesized lifetime bounds are not supported" ) ;
4101
+ }
4084
4102
} else if self . check_keyword ( keywords:: For ) || self . check_path ( ) {
4085
4103
let lo = self . span ;
4086
4104
let lifetime_defs = self . parse_late_bound_lifetime_defs ( ) ?;
@@ -4092,6 +4110,9 @@ impl<'a> Parser<'a> {
4092
4110
TraitBoundModifier :: None
4093
4111
} ;
4094
4112
bounds. push ( TraitTyParamBound ( poly_trait, modifier) ) ;
4113
+ if has_parens {
4114
+ self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
4115
+ }
4095
4116
} else {
4096
4117
break
4097
4118
}
0 commit comments