@@ -1528,6 +1528,7 @@ impl<'a> Parser<'a> {
1528
1528
maybe_whole ! ( self , NtTy , |x| x) ;
1529
1529
1530
1530
let lo = self . span ;
1531
+ let mut impl_dyn_multi = false ;
1531
1532
let node = if self . eat ( & token:: OpenDelim ( token:: Paren ) ) {
1532
1533
// `(TYPE)` is a parenthesized type.
1533
1534
// `(TYPE,)` is a tuple with a single field of type TYPE.
@@ -1614,12 +1615,17 @@ impl<'a> Parser<'a> {
1614
1615
self . parse_remaining_bounds ( lifetime_defs, path, lo, parse_plus) ?
1615
1616
}
1616
1617
} else if self . eat_keyword ( keywords:: Impl ) {
1617
- TyKind :: ImplTrait ( self . parse_ty_param_bounds_common ( allow_plus) ?)
1618
+ // Always parse bounds greedily for better error recovery.
1619
+ let bounds = self . parse_ty_param_bounds ( ) ?;
1620
+ impl_dyn_multi = bounds. len ( ) > 1 || self . prev_token_kind == PrevTokenKind :: Plus ;
1621
+ TyKind :: ImplTrait ( bounds)
1618
1622
} else if self . check_keyword ( keywords:: Dyn ) &&
1619
1623
self . look_ahead ( 1 , |t| t. can_begin_bound ( ) && !can_continue_type_after_ident ( t) ) {
1620
1624
self . bump ( ) ; // `dyn`
1621
- TyKind :: TraitObject ( self . parse_ty_param_bounds_common ( allow_plus) ?,
1622
- TraitObjectSyntax :: Dyn )
1625
+ // Always parse bounds greedily for better error recovery.
1626
+ let bounds = self . parse_ty_param_bounds ( ) ?;
1627
+ impl_dyn_multi = bounds. len ( ) > 1 || self . prev_token_kind == PrevTokenKind :: Plus ;
1628
+ TyKind :: TraitObject ( bounds, TraitObjectSyntax :: Dyn )
1623
1629
} else if self . check ( & token:: Question ) ||
1624
1630
self . check_lifetime ( ) && self . look_ahead ( 1 , |t| t == & token:: BinOp ( token:: Plus ) ) {
1625
1631
// Bound list (trait object type)
@@ -1655,6 +1661,7 @@ impl<'a> Parser<'a> {
1655
1661
let ty = Ty { node, span, id : ast:: DUMMY_NODE_ID } ;
1656
1662
1657
1663
// Try to recover from use of `+` with incorrect priority.
1664
+ self . maybe_report_ambiguous_plus ( allow_plus, impl_dyn_multi, & ty) ;
1658
1665
self . maybe_recover_from_bad_type_plus ( allow_plus, & ty) ?;
1659
1666
let ty = self . maybe_recover_from_bad_qpath ( ty, allow_qpath_recovery) ?;
1660
1667
@@ -1672,6 +1679,15 @@ impl<'a> Parser<'a> {
1672
1679
Ok ( TyKind :: TraitObject ( bounds, TraitObjectSyntax :: None ) )
1673
1680
}
1674
1681
1682
+ fn maybe_report_ambiguous_plus ( & mut self , allow_plus : bool , impl_dyn_multi : bool , ty : & Ty ) {
1683
+ if !allow_plus && impl_dyn_multi {
1684
+ let sum_with_parens = format ! ( "({})" , pprust:: ty_to_string( & ty) ) ;
1685
+ self . struct_span_err ( ty. span , "ambiguous `+` in a type" )
1686
+ . span_suggestion ( ty. span , "use parentheses to disambiguate" , sum_with_parens)
1687
+ . emit ( ) ;
1688
+ }
1689
+ }
1690
+
1675
1691
fn maybe_recover_from_bad_type_plus ( & mut self , allow_plus : bool , ty : & Ty ) -> PResult < ' a , ( ) > {
1676
1692
// Do not add `+` to expected tokens.
1677
1693
if !allow_plus || self . token != token:: BinOp ( token:: Plus ) {
0 commit comments