@@ -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,26 @@ 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 ) => {
1365
- self . bump ( ) ; // `+`
1366
- let pt = PolyTraitRef :: new ( Vec :: new ( ) , path. clone ( ) , lo. to ( self . prev_span ) ) ;
1367
- let mut bounds = vec ! [ TraitTyParamBound ( pt, TraitBoundModifier :: None ) ] ;
1368
- bounds. append ( & mut self . parse_ty_param_bounds ( ) ?) ;
1369
- TyKind :: TraitObject ( bounds)
1366
+ // `(TY_BOUND_NOPAREN) + BOUND + ...`.
1367
+ TyKind :: Path ( None , ref path) if maybe_bounds => {
1368
+ self . parse_remaining_bounds ( Vec :: new ( ) , path. clone ( ) , lo, true ) ?
1370
1369
}
1370
+ TyKind :: TraitObject ( ref bounds)
1371
+ if maybe_bounds && bounds. len ( ) == 1 && !trailing_plus => {
1372
+ let path = match bounds[ 0 ] {
1373
+ TraitTyParamBound ( ref pt, ..) => pt. trait_ref . path . clone ( ) ,
1374
+ _ => self . bug ( "unexpected lifetime bound" ) ,
1375
+ } ;
1376
+ self . parse_remaining_bounds ( Vec :: new ( ) , path, lo, true ) ?
1377
+ }
1378
+ // `(TYPE)`
1371
1379
_ => TyKind :: Paren ( P ( ty) )
1372
1380
}
1373
1381
} else {
@@ -1418,11 +1426,8 @@ impl<'a> Parser<'a> {
1418
1426
// Just a type path or bound list (trait object type) starting with a trait.
1419
1427
// `Type`
1420
1428
// `Trait1 + Trait2 + 'a`
1421
- if allow_plus && self . eat ( & token:: BinOp ( token:: Plus ) ) {
1422
- let poly_trait = PolyTraitRef :: new ( Vec :: new ( ) , path, lo. to ( self . prev_span ) ) ;
1423
- let mut bounds = vec ! [ TraitTyParamBound ( poly_trait, TraitBoundModifier :: None ) ] ;
1424
- bounds. append ( & mut self . parse_ty_param_bounds ( ) ?) ;
1425
- TyKind :: TraitObject ( bounds)
1429
+ if allow_plus && self . check ( & token:: BinOp ( token:: Plus ) ) {
1430
+ self . parse_remaining_bounds ( Vec :: new ( ) , path, lo, true ) ?
1426
1431
} else {
1427
1432
TyKind :: Path ( None , path)
1428
1433
}
@@ -1440,12 +1445,8 @@ impl<'a> Parser<'a> {
1440
1445
self . parse_ty_bare_fn ( lifetime_defs) ?
1441
1446
} else {
1442
1447
let path = self . parse_path ( PathStyle :: Type ) ?;
1443
- let poly_trait = PolyTraitRef :: new ( lifetime_defs, path, lo. to ( self . prev_span ) ) ;
1444
- let mut bounds = vec ! [ TraitTyParamBound ( poly_trait, TraitBoundModifier :: None ) ] ;
1445
- if allow_plus && self . eat ( & token:: BinOp ( token:: Plus ) ) {
1446
- bounds. append ( & mut self . parse_ty_param_bounds ( ) ?)
1447
- }
1448
- TyKind :: TraitObject ( bounds)
1448
+ let parse_plus = allow_plus && self . check ( & token:: BinOp ( token:: Plus ) ) ;
1449
+ self . parse_remaining_bounds ( lifetime_defs, path, lo, parse_plus) ?
1449
1450
}
1450
1451
} else if self . eat_keyword ( keywords:: Impl ) {
1451
1452
// FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511).
@@ -1468,6 +1469,17 @@ impl<'a> Parser<'a> {
1468
1469
Ok ( P ( ty) )
1469
1470
}
1470
1471
1472
+ fn parse_remaining_bounds ( & mut self , lifetime_defs : Vec < LifetimeDef > , path : ast:: Path ,
1473
+ lo : Span , parse_plus : bool ) -> PResult < ' a , TyKind > {
1474
+ let poly_trait_ref = PolyTraitRef :: new ( lifetime_defs, path, lo. to ( self . prev_span ) ) ;
1475
+ let mut bounds = vec ! [ TraitTyParamBound ( poly_trait_ref, TraitBoundModifier :: None ) ] ;
1476
+ if parse_plus {
1477
+ self . bump ( ) ; // `+`
1478
+ bounds. append ( & mut self . parse_ty_param_bounds ( ) ?) ;
1479
+ }
1480
+ Ok ( TyKind :: TraitObject ( bounds) )
1481
+ }
1482
+
1471
1483
fn maybe_recover_from_bad_type_plus ( & mut self , allow_plus : bool , ty : & Ty ) -> PResult < ' a , ( ) > {
1472
1484
// Do not add `+` to expected tokens.
1473
1485
if !allow_plus || self . token != token:: BinOp ( token:: Plus ) {
@@ -4070,28 +4082,43 @@ impl<'a> Parser<'a> {
4070
4082
// Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
4071
4083
// BOUND = TY_BOUND | LT_BOUND
4072
4084
// LT_BOUND = LIFETIME (e.g. `'a`)
4073
- // TY_BOUND = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`)
4085
+ // TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
4086
+ // TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`)
4074
4087
fn parse_ty_param_bounds_common ( & mut self , allow_plus : bool ) -> PResult < ' a , TyParamBounds > {
4075
4088
let mut bounds = Vec :: new ( ) ;
4076
4089
loop {
4077
- let question = if self . eat ( & token:: Question ) { Some ( self . prev_span ) } else { None } ;
4078
- if self . check_lifetime ( ) {
4079
- if let Some ( question_span) = question {
4080
- self . span_err ( question_span,
4081
- "`?` may only modify trait bounds, not lifetime bounds" ) ;
4082
- }
4083
- bounds. push ( RegionTyParamBound ( self . expect_lifetime ( ) ) ) ;
4084
- } else if self . check_keyword ( keywords:: For ) || self . check_path ( ) {
4085
- let lo = self . span ;
4086
- let lifetime_defs = self . parse_late_bound_lifetime_defs ( ) ?;
4087
- let path = self . parse_path ( PathStyle :: Type ) ?;
4088
- let poly_trait = PolyTraitRef :: new ( lifetime_defs, path, lo. to ( self . prev_span ) ) ;
4089
- let modifier = if question. is_some ( ) {
4090
- TraitBoundModifier :: Maybe
4090
+ let is_bound_start = self . check_path ( ) || self . check_lifetime ( ) ||
4091
+ self . check ( & token:: Question ) ||
4092
+ self . check_keyword ( keywords:: For ) ||
4093
+ self . check ( & token:: OpenDelim ( token:: Paren ) ) ;
4094
+ if is_bound_start {
4095
+ let has_parens = self . eat ( & token:: OpenDelim ( token:: Paren ) ) ;
4096
+ let question = if self . eat ( & token:: Question ) { Some ( self . prev_span ) } else { None } ;
4097
+ if self . token . is_lifetime ( ) {
4098
+ if let Some ( question_span) = question {
4099
+ self . span_err ( question_span,
4100
+ "`?` may only modify trait bounds, not lifetime bounds" ) ;
4101
+ }
4102
+ bounds. push ( RegionTyParamBound ( self . expect_lifetime ( ) ) ) ;
4091
4103
} else {
4092
- TraitBoundModifier :: None
4093
- } ;
4094
- bounds. push ( TraitTyParamBound ( poly_trait, modifier) ) ;
4104
+ let lo = self . span ;
4105
+ let lifetime_defs = self . parse_late_bound_lifetime_defs ( ) ?;
4106
+ let path = self . parse_path ( PathStyle :: Type ) ?;
4107
+ let poly_trait = PolyTraitRef :: new ( lifetime_defs, path, lo. to ( self . prev_span ) ) ;
4108
+ let modifier = if question. is_some ( ) {
4109
+ TraitBoundModifier :: Maybe
4110
+ } else {
4111
+ TraitBoundModifier :: None
4112
+ } ;
4113
+ bounds. push ( TraitTyParamBound ( poly_trait, modifier) ) ;
4114
+ }
4115
+ if has_parens {
4116
+ self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?;
4117
+ if let Some ( & RegionTyParamBound ( ..) ) = bounds. last ( ) {
4118
+ self . span_err ( self . prev_span ,
4119
+ "parenthesized lifetime bounds are not supported" ) ;
4120
+ }
4121
+ }
4095
4122
} else {
4096
4123
break
4097
4124
}
0 commit comments