@@ -2608,53 +2608,59 @@ impl<'a> Parser<'a> {
2608
2608
}
2609
2609
2610
2610
fn parse_for_head ( & mut self ) -> PResult < ' a , ( P < Pat > , P < Expr > ) > {
2611
- let pat = if self . token . kind == token:: OpenDelim ( Delimiter :: Parenthesis ) {
2611
+ let begin_paren = if self . token . kind == token:: OpenDelim ( Delimiter :: Parenthesis ) {
2612
2612
// Record whether we are about to parse `for (`.
2613
2613
// This is used below for recovery in case of `for ( $stuff ) $block`
2614
2614
// in which case we will suggest `for $stuff $block`.
2615
2615
let start_span = self . token . span ;
2616
2616
let left = self . prev_token . span . between ( self . look_ahead ( 1 , |t| t. span ) ) ;
2617
- match self . parse_pat_allow_top_alt (
2618
- None ,
2619
- RecoverComma :: Yes ,
2620
- RecoverColon :: Yes ,
2621
- CommaRecoveryMode :: LikelyTuple ,
2622
- ) {
2623
- Ok ( pat) => pat,
2624
- Err ( err) if self . eat_keyword ( kw:: In ) => {
2625
- let expr = match self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL , None ) {
2626
- Ok ( expr) => expr,
2627
- Err ( expr_err) => {
2628
- expr_err. cancel ( ) ;
2629
- return Err ( err) ;
2630
- }
2631
- } ;
2632
- return if self . token . kind == token:: CloseDelim ( Delimiter :: Parenthesis ) {
2633
- let span = vec ! [ start_span, self . token. span] ;
2634
- let right = self . prev_token . span . between ( self . look_ahead ( 1 , |t| t. span ) ) ;
2635
- self . bump ( ) ; // )
2636
- err. cancel ( ) ;
2637
- self . sess . emit_err ( errors:: ParenthesesInForHead {
2638
- span,
2639
- // With e.g. `for (x) in y)` this would replace `(x) in y)`
2640
- // with `x) in y)` which is syntactically invalid.
2641
- // However, this is prevented before we get here.
2642
- sugg : errors:: ParenthesesInForHeadSugg { left, right } ,
2643
- } ) ;
2644
- Ok ( ( self . mk_pat ( start_span. to ( right) , ast:: PatKind :: Wild ) , expr) )
2645
- } else {
2646
- Err ( err)
2647
- } ;
2648
- }
2649
- Err ( err) => return Err ( err) ,
2650
- }
2617
+ Some ( ( start_span, left) )
2651
2618
} else {
2619
+ None
2620
+ } ;
2621
+ // Try to parse the pattern `for ($PAT) in $EXPR`.
2622
+ let pat = match (
2652
2623
self . parse_pat_allow_top_alt (
2653
2624
None ,
2654
2625
RecoverComma :: Yes ,
2655
2626
RecoverColon :: Yes ,
2656
2627
CommaRecoveryMode :: LikelyTuple ,
2657
- ) ?
2628
+ ) ,
2629
+ begin_paren,
2630
+ ) {
2631
+ ( Ok ( pat) , _) => pat, // Happy path.
2632
+ ( Err ( err) , Some ( ( start_span, left) ) ) if self . eat_keyword ( kw:: In ) => {
2633
+ // We know for sure we have seen `for ($SOMETHING in`. In the happy path this would
2634
+ // happen right before the return of this method.
2635
+ let expr = match self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL , None ) {
2636
+ Ok ( expr) => expr,
2637
+ Err ( expr_err) => {
2638
+ // We don't know what followed the `in`, so cancel and bubble up the
2639
+ // original error.
2640
+ expr_err. cancel ( ) ;
2641
+ return Err ( err) ;
2642
+ }
2643
+ } ;
2644
+ return if self . token . kind == token:: CloseDelim ( Delimiter :: Parenthesis ) {
2645
+ // We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the
2646
+ // parser state and emit a targetted suggestion.
2647
+ let span = vec ! [ start_span, self . token. span] ;
2648
+ let right = self . prev_token . span . between ( self . look_ahead ( 1 , |t| t. span ) ) ;
2649
+ self . bump ( ) ; // )
2650
+ err. cancel ( ) ;
2651
+ self . sess . emit_err ( errors:: ParenthesesInForHead {
2652
+ span,
2653
+ // With e.g. `for (x) in y)` this would replace `(x) in y)`
2654
+ // with `x) in y)` which is syntactically invalid.
2655
+ // However, this is prevented before we get here.
2656
+ sugg : errors:: ParenthesesInForHeadSugg { left, right } ,
2657
+ } ) ;
2658
+ Ok ( ( self . mk_pat ( start_span. to ( right) , ast:: PatKind :: Wild ) , expr) )
2659
+ } else {
2660
+ Err ( err) // Some other error, bubble up.
2661
+ } ;
2662
+ }
2663
+ ( Err ( err) , _) => return Err ( err) , // Some other error, bubble up.
2658
2664
} ;
2659
2665
if !self . eat_keyword ( kw:: In ) {
2660
2666
self . error_missing_in_for_loop ( ) ;
0 commit comments