Skip to content

Commit 9ae5b7c

Browse files
committed
review comment: rework parse_for_head to reduce branching
1 parent 48576ce commit 9ae5b7c

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
@@ -2608,53 +2608,59 @@ impl<'a> Parser<'a> {
26082608
}
26092609

26102610
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) {
26122612
// Record whether we are about to parse `for (`.
26132613
// This is used below for recovery in case of `for ( $stuff ) $block`
26142614
// in which case we will suggest `for $stuff $block`.
26152615
let start_span = self.token.span;
26162616
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))
26512618
} else {
2619+
None
2620+
};
2621+
// Try to parse the pattern `for ($PAT) in $EXPR`.
2622+
let pat = match (
26522623
self.parse_pat_allow_top_alt(
26532624
None,
26542625
RecoverComma::Yes,
26552626
RecoverColon::Yes,
26562627
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.
26582664
};
26592665
if !self.eat_keyword(kw::In) {
26602666
self.error_missing_in_for_loop();

0 commit comments

Comments
 (0)