Skip to content

Commit 31f08e9

Browse files
committed
review comment: rework parse_for_head to reduce branching
1 parent 39f6aa2 commit 31f08e9

File tree

1 file changed

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

1 file changed

+40
-36
lines changed

compiler/rustc_parse/src/parser/expr.rs

+40-36
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)