Skip to content

Commit fc6451f

Browse files
committed
review comment: rework parse_for_head to reduce branching
1 parent 76a19c0 commit fc6451f

File tree

1 file changed

+42
-36
lines changed
  • compiler/rustc_parse/src/parser

1 file changed

+42
-36
lines changed

compiler/rustc_parse/src/parser/expr.rs

+42-36
Original file line numberDiff line numberDiff line change
@@ -2610,53 +2610,59 @@ impl<'a> Parser<'a> {
26102610
}
26112611

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

0 commit comments

Comments
 (0)