@@ -2592,53 +2592,57 @@ impl<'a> Parser<'a> {
2592
2592
}
2593
2593
2594
2594
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 ) {
2596
2596
// Record whether we are about to parse `for (`.
2597
2597
// This is used below for recovery in case of `for ( $stuff ) $block`
2598
2598
// in which case we will suggest `for $stuff $block`.
2599
2599
let start_span = self . token . span ;
2600
2600
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) )
2635
2602
} else {
2603
+ None
2604
+ } ;
2605
+ let pat = match (
2636
2606
self . parse_pat_allow_top_alt (
2637
2607
None ,
2638
2608
RecoverComma :: Yes ,
2639
2609
RecoverColon :: Yes ,
2640
2610
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) ,
2642
2646
} ;
2643
2647
if !self . eat_keyword ( kw:: In ) {
2644
2648
self . error_missing_in_for_loop ( ) ;
0 commit comments