@@ -2592,53 +2592,57 @@ impl<'a> Parser<'a> {
25922592    } 
25932593
25942594    fn  parse_for_head ( & mut  self )  -> PResult < ' a ,  ( P < Pat > ,  P < Expr > ) >  { 
2595-         let  pat  = if  self . token . kind  == token:: OpenDelim ( Delimiter :: Parenthesis )  { 
2595+         let  begin_paren  = if  self . token . kind  == token:: OpenDelim ( Delimiter :: Parenthesis )  { 
25962596            // Record whether we are about to parse `for (`. 
25972597            // This is used below for recovery in case of `for ( $stuff ) $block` 
25982598            // in which case we will suggest `for $stuff $block`. 
25992599            let  start_span = self . token . span ; 
26002600            let  left = self . prev_token . span . between ( self . look_ahead ( 1 ,  |t| t. span ) ) ; 
2601-             match  self . parse_pat_allow_top_alt ( 
2602-                 None , 
2603-                 RecoverComma :: Yes , 
2604-                 RecoverColon :: Yes , 
2605-                 CommaRecoveryMode :: LikelyTuple , 
2606-             )  { 
2607-                 Ok ( pat)  => pat, 
2608-                 Err ( err)  if  self . eat_keyword ( kw:: In )  => { 
2609-                     let  expr = match  self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL ,  None )  { 
2610-                         Ok ( expr)  => expr, 
2611-                         Err ( expr_err)  => { 
2612-                             expr_err. cancel ( ) ; 
2613-                             return  Err ( err) ; 
2614-                         } 
2615-                     } ; 
2616-                     return  if  self . token . kind  == token:: CloseDelim ( Delimiter :: Parenthesis )  { 
2617-                         let  span = vec ! [ start_span,  self . token. span] ; 
2618-                         let  right = self . prev_token . span . between ( self . look_ahead ( 1 ,  |t| t. span ) ) ; 
2619-                         self . bump ( ) ;  // ) 
2620-                         err. cancel ( ) ; 
2621-                         self . sess . emit_err ( errors:: ParenthesesInForHead  { 
2622-                             span, 
2623-                             // With e.g. `for (x) in y)` this would replace `(x) in y)` 
2624-                             // with `x) in y)` which is syntactically invalid. 
2625-                             // However, this is prevented before we get here. 
2626-                             sugg :  errors:: ParenthesesInForHeadSugg  {  left,  right } , 
2627-                         } ) ; 
2628-                         Ok ( ( self . mk_pat ( start_span. to ( right) ,  ast:: PatKind :: Wild ) ,  expr) ) 
2629-                     }  else  { 
2630-                         Err ( err) 
2631-                     } ; 
2632-                 } 
2633-                 Err ( err)  => return  Err ( err) , 
2634-             } 
2601+             Some ( ( start_span,  left) ) 
26352602        }  else  { 
2603+             None 
2604+         } ; 
2605+         let  pat = match  ( 
26362606            self . parse_pat_allow_top_alt ( 
26372607                None , 
26382608                RecoverComma :: Yes , 
26392609                RecoverColon :: Yes , 
26402610                CommaRecoveryMode :: LikelyTuple , 
2641-             ) ?
2611+             ) , 
2612+             begin_paren, 
2613+         )  { 
2614+             ( Ok ( pat) ,  _)  => pat, 
2615+             ( Err ( err) ,  Some ( ( start_span,  left) ) )  if  self . eat_keyword ( kw:: In )  => { 
2616+                 // We know for sure we have seen `for ($SOMETHING in`. 
2617+                 let  expr = match  self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL ,  None )  { 
2618+                     Ok ( expr)  => expr, 
2619+                     Err ( expr_err)  => { 
2620+                         // We don't know what followed the `in`, so cancel and bubble up the 
2621+                         // original error. 
2622+                         expr_err. cancel ( ) ; 
2623+                         return  Err ( err) ; 
2624+                     } 
2625+                 } ; 
2626+                 return  if  self . token . kind  == token:: CloseDelim ( Delimiter :: Parenthesis )  { 
2627+                     // We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the 
2628+                     // parser state and emit a targetted suggestion. 
2629+                     let  span = vec ! [ start_span,  self . token. span] ; 
2630+                     let  right = self . prev_token . span . between ( self . look_ahead ( 1 ,  |t| t. span ) ) ; 
2631+                     self . bump ( ) ;  // ) 
2632+                     err. cancel ( ) ; 
2633+                     self . sess . emit_err ( errors:: ParenthesesInForHead  { 
2634+                         span, 
2635+                         // With e.g. `for (x) in y)` this would replace `(x) in y)` 
2636+                         // with `x) in y)` which is syntactically invalid. 
2637+                         // However, this is prevented before we get here. 
2638+                         sugg :  errors:: ParenthesesInForHeadSugg  {  left,  right } , 
2639+                     } ) ; 
2640+                     Ok ( ( self . mk_pat ( start_span. to ( right) ,  ast:: PatKind :: Wild ) ,  expr) ) 
2641+                 }  else  { 
2642+                     Err ( err) 
2643+                 } ; 
2644+             } 
2645+             ( Err ( err) ,  _)  => return  Err ( err) , 
26422646        } ; 
26432647        if  !self . eat_keyword ( kw:: In )  { 
26442648            self . error_missing_in_for_loop ( ) ; 
0 commit comments