@@ -33,7 +33,7 @@ use ast::{Stmt, StmtKind};
33
33
use ast:: { VariantData , StructField } ;
34
34
use ast:: StrStyle ;
35
35
use ast:: SelfKind ;
36
- use ast:: { TraitItem , TraitRef } ;
36
+ use ast:: { TraitItem , TraitRef , TraitObjectSyntax } ;
37
37
use ast:: { Ty , TyKind , TypeBinding , TyParam , TyParamBounds } ;
38
38
use ast:: { ViewPath , ViewPathGlob , ViewPathList , ViewPathSimple } ;
39
39
use ast:: { Visibility , WhereClause } ;
@@ -364,6 +364,13 @@ fn is_ident_or_underscore(t: &token::Token) -> bool {
364
364
t. is_ident ( ) || * t == token:: Underscore
365
365
}
366
366
367
+ // Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
368
+ // `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
369
+ fn can_continue_type_after_ident ( t : & token:: Token ) -> bool {
370
+ t == & token:: ModSep || t == & token:: Lt ||
371
+ t == & token:: BinOp ( token:: Shl ) || t == & token:: OpenDelim ( token:: Paren )
372
+ }
373
+
367
374
/// Information about the path to a module.
368
375
pub struct ModulePath {
369
376
pub name : String ,
@@ -1428,7 +1435,7 @@ impl<'a> Parser<'a> {
1428
1435
TyKind :: Path ( None , ref path) if maybe_bounds => {
1429
1436
self . parse_remaining_bounds ( Vec :: new ( ) , path. clone ( ) , lo, true ) ?
1430
1437
}
1431
- TyKind :: TraitObject ( ref bounds)
1438
+ TyKind :: TraitObject ( ref bounds, TraitObjectSyntax :: None )
1432
1439
if maybe_bounds && bounds. len ( ) == 1 && !trailing_plus => {
1433
1440
let path = match bounds[ 0 ] {
1434
1441
TraitTyParamBound ( ref pt, ..) => pt. trait_ref . path . clone ( ) ,
@@ -1472,27 +1479,6 @@ impl<'a> Parser<'a> {
1472
1479
} else if self . eat ( & token:: Underscore ) {
1473
1480
// A type to be inferred `_`
1474
1481
TyKind :: Infer
1475
- } else if self . eat_lt ( ) {
1476
- // Qualified path
1477
- let ( qself, path) = self . parse_qpath ( PathStyle :: Type ) ?;
1478
- TyKind :: Path ( Some ( qself) , path)
1479
- } else if self . token . is_path_start ( ) {
1480
- // Simple path
1481
- let path = self . parse_path ( PathStyle :: Type ) ?;
1482
- if self . eat ( & token:: Not ) {
1483
- // Macro invocation in type position
1484
- let ( _, tts) = self . expect_delimited_token_tree ( ) ?;
1485
- TyKind :: Mac ( respan ( lo. to ( self . span ) , Mac_ { path : path, tts : tts } ) )
1486
- } else {
1487
- // Just a type path or bound list (trait object type) starting with a trait.
1488
- // `Type`
1489
- // `Trait1 + Trait2 + 'a`
1490
- if allow_plus && self . check ( & token:: BinOp ( token:: Plus ) ) {
1491
- self . parse_remaining_bounds ( Vec :: new ( ) , path, lo, true ) ?
1492
- } else {
1493
- TyKind :: Path ( None , path)
1494
- }
1495
- }
1496
1482
} else if self . token_is_bare_fn_keyword ( ) {
1497
1483
// Function pointer type
1498
1484
self . parse_ty_bare_fn ( Vec :: new ( ) ) ?
@@ -1512,10 +1498,37 @@ impl<'a> Parser<'a> {
1512
1498
} else if self . eat_keyword ( keywords:: Impl ) {
1513
1499
// FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511).
1514
1500
TyKind :: ImplTrait ( self . parse_ty_param_bounds ( ) ?)
1501
+ } else if self . check_keyword ( keywords:: Dyn ) &&
1502
+ self . look_ahead ( 1 , |t| t. can_begin_bound ( ) && !can_continue_type_after_ident ( t) ) {
1503
+ // FIXME: figure out priority of `+` in `dyn Trait1 + Trait2` (#34511).
1504
+ self . bump ( ) ; // `dyn`
1505
+ TyKind :: TraitObject ( self . parse_ty_param_bounds ( ) ?, TraitObjectSyntax :: Dyn )
1515
1506
} else if self . check ( & token:: Question ) ||
1516
- self . check_lifetime ( ) && self . look_ahead ( 1 , |t| t == & token:: BinOp ( token:: Plus ) ) {
1507
+ self . check_lifetime ( ) && self . look_ahead ( 1 , |t| t == & token:: BinOp ( token:: Plus ) ) {
1517
1508
// Bound list (trait object type)
1518
- TyKind :: TraitObject ( self . parse_ty_param_bounds_common ( allow_plus) ?)
1509
+ TyKind :: TraitObject ( self . parse_ty_param_bounds_common ( allow_plus) ?,
1510
+ TraitObjectSyntax :: None )
1511
+ } else if self . eat_lt ( ) {
1512
+ // Qualified path
1513
+ let ( qself, path) = self . parse_qpath ( PathStyle :: Type ) ?;
1514
+ TyKind :: Path ( Some ( qself) , path)
1515
+ } else if self . token . is_path_start ( ) {
1516
+ // Simple path
1517
+ let path = self . parse_path ( PathStyle :: Type ) ?;
1518
+ if self . eat ( & token:: Not ) {
1519
+ // Macro invocation in type position
1520
+ let ( _, tts) = self . expect_delimited_token_tree ( ) ?;
1521
+ TyKind :: Mac ( respan ( lo. to ( self . span ) , Mac_ { path : path, tts : tts } ) )
1522
+ } else {
1523
+ // Just a type path or bound list (trait object type) starting with a trait.
1524
+ // `Type`
1525
+ // `Trait1 + Trait2 + 'a`
1526
+ if allow_plus && self . check ( & token:: BinOp ( token:: Plus ) ) {
1527
+ self . parse_remaining_bounds ( Vec :: new ( ) , path, lo, true ) ?
1528
+ } else {
1529
+ TyKind :: Path ( None , path)
1530
+ }
1531
+ }
1519
1532
} else {
1520
1533
let msg = format ! ( "expected type, found {}" , self . this_token_descr( ) ) ;
1521
1534
return Err ( self . fatal ( & msg) ) ;
@@ -1538,7 +1551,7 @@ impl<'a> Parser<'a> {
1538
1551
self . bump ( ) ; // `+`
1539
1552
bounds. append ( & mut self . parse_ty_param_bounds ( ) ?) ;
1540
1553
}
1541
- Ok ( TyKind :: TraitObject ( bounds) )
1554
+ Ok ( TyKind :: TraitObject ( bounds, TraitObjectSyntax :: None ) )
1542
1555
}
1543
1556
1544
1557
fn maybe_recover_from_bad_type_plus ( & mut self , allow_plus : bool , ty : & Ty ) -> PResult < ' a , ( ) > {
@@ -4256,6 +4269,7 @@ impl<'a> Parser<'a> {
4256
4269
fn parse_ty_param_bounds_common ( & mut self , allow_plus : bool ) -> PResult < ' a , TyParamBounds > {
4257
4270
let mut bounds = Vec :: new ( ) ;
4258
4271
loop {
4272
+ // This needs to be syncronized with `Token::can_begin_bound`.
4259
4273
let is_bound_start = self . check_path ( ) || self . check_lifetime ( ) ||
4260
4274
self . check ( & token:: Question ) ||
4261
4275
self . check_keyword ( keywords:: For ) ||
0 commit comments