@@ -250,6 +250,8 @@ pub struct Parser<'a> {
250250 desugar_doc_comments : bool ,
251251 /// Whether we should configure out of line modules as we parse.
252252 pub cfg_mods : bool ,
253+ /// Whether we should prevent recovery from parsing areas (during backtracking).
254+ prevent_recovery : bool ,
253255}
254256
255257
@@ -569,6 +571,7 @@ impl<'a> Parser<'a> {
569571 } ,
570572 desugar_doc_comments,
571573 cfg_mods : true ,
574+ prevent_recovery : false ,
572575 } ;
573576
574577 let tok = parser. next_tok ( ) ;
@@ -1111,6 +1114,9 @@ impl<'a> Parser<'a> {
11111114 first = false ;
11121115 } else {
11131116 if let Err ( mut e) = self . expect ( t) {
1117+ if self . prevent_recovery {
1118+ return Err ( e) ;
1119+ }
11141120 // Attempt to keep parsing if it was a similar separator
11151121 if let Some ( ref tokens) = t. similar_tokens ( ) {
11161122 if tokens. contains ( & self . token ) {
@@ -1725,11 +1731,10 @@ impl<'a> Parser<'a> {
17251731 } else if self . eat_keyword ( keywords:: Const ) {
17261732 Mutability :: Immutable
17271733 } else {
1728- let span = self . prev_span ;
1729- self . span_err ( span,
1730- "expected mut or const in raw pointer type (use \
1731- `*mut T` or `*const T` as appropriate)") ;
1732- Mutability :: Immutable
1734+ let mut err = self . fatal ( "expected mut or const in raw pointer type (use \
1735+ `*mut T` or `*const T` as appropriate)") ;
1736+ err. span_label ( self . prev_span , "expected mut or const" ) ;
1737+ return Err ( err) ;
17331738 } ;
17341739 let t = self . parse_ty_no_plus ( ) ?;
17351740 Ok ( MutTy { ty : t, mutbl : mutbl } )
@@ -2041,20 +2046,32 @@ impl<'a> Parser<'a> {
20412046 -> PResult < ' a , PathSegment > {
20422047 let ident = self . parse_path_segment_ident ( ) ?;
20432048
2044- let is_args_start = |token : & token:: Token | match * token {
2045- token:: Lt | token:: BinOp ( token:: Shl ) | token:: OpenDelim ( token:: Paren ) => true ,
2049+ let is_args_start = |token : & token:: Token , include_paren : bool | match * token {
2050+ token:: Lt | token:: BinOp ( token:: Shl ) => true ,
2051+ token:: OpenDelim ( token:: Paren ) => include_paren,
20462052 _ => false ,
20472053 } ;
2048- let check_args_start = |this : & mut Self | {
2049- this. expected_tokens . extend_from_slice (
2050- & [ TokenType :: Token ( token:: Lt ) , TokenType :: Token ( token:: OpenDelim ( token:: Paren ) ) ]
2051- ) ;
2052- is_args_start ( & this. token )
2054+ let check_args_start = |this : & mut Self , include_paren : bool | {
2055+ this. expected_tokens . push ( TokenType :: Token ( token:: Lt ) ) ;
2056+ if include_paren {
2057+ this. expected_tokens . push ( TokenType :: Token ( token:: OpenDelim ( token:: Paren ) ) ) ;
2058+ }
2059+ is_args_start ( & this. token , include_paren)
20532060 } ;
20542061
2055- Ok ( if style == PathStyle :: Type && check_args_start ( self ) ||
2056- style != PathStyle :: Mod && self . check ( & token:: ModSep )
2057- && self . look_ahead ( 1 , |t| is_args_start ( t) ) {
2062+ let mut parser_snapshot_before_generics = None ;
2063+
2064+ Ok ( if style == PathStyle :: Type && check_args_start ( self , true )
2065+ || style != PathStyle :: Mod && self . check ( & token:: ModSep )
2066+ && self . look_ahead ( 1 , |t| is_args_start ( t, true ) )
2067+ || style == PathStyle :: Expr && check_args_start ( self , false ) && {
2068+ // Check for generic arguments in an expression without a disambiguating `::`.
2069+ // We have to save a snapshot, because it could end up being an expression
2070+ // instead.
2071+ parser_snapshot_before_generics = Some ( self . clone ( ) ) ;
2072+ self . prevent_recovery = true ;
2073+ true
2074+ } {
20582075 // Generic arguments are found - `<`, `(`, `::<` or `::(`.
20592076 let lo = self . span ;
20602077 if self . eat ( & token:: ModSep ) && style == PathStyle :: Type && enable_warning {
@@ -2064,10 +2081,26 @@ impl<'a> Parser<'a> {
20642081
20652082 let args = if self . eat_lt ( ) {
20662083 // `<'a, T, A = U>`
2067- let ( args, bindings) = self . parse_generic_args ( ) ?;
2068- self . expect_gt ( ) ?;
2069- let span = lo. to ( self . prev_span ) ;
2070- AngleBracketedArgs { args, bindings, span } . into ( )
2084+ let args: PResult < _ > = do catch {
2085+ let ( args, bindings) = self . parse_generic_args ( ) ?;
2086+ self . expect_gt ( ) ?;
2087+ let span = lo. to ( self . prev_span ) ;
2088+ AngleBracketedArgs { args, bindings, span }
2089+ } ;
2090+
2091+ match args {
2092+ Err ( mut err) => {
2093+ if let Some ( snapshot) = parser_snapshot_before_generics {
2094+ err. cancel ( ) ;
2095+ mem:: replace ( self , snapshot) ;
2096+ return Ok ( PathSegment :: from_ident ( ident) ) ;
2097+ }
2098+ return Err ( err) ;
2099+ }
2100+ _ => {
2101+ args?. into ( )
2102+ }
2103+ }
20712104 } else {
20722105 // `(T, U) -> R`
20732106 self . bump ( ) ; // `(`
0 commit comments