New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recover from if (let ...)
in parsing, instead of lowering
#83407
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1765,7 +1765,20 @@ impl<'a> Parser<'a> { | |
/// Parses an `if` expression (`if` token already eaten). | ||
fn parse_if_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { | ||
let lo = self.prev_token.span; | ||
let cond = self.parse_cond_expr()?; | ||
let mut cond = self.parse_cond_expr()?.into_inner(); | ||
|
||
if let ExprKind::Paren(paren) = &cond.kind { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We still need the feature gate check we talked about here, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's blocked currently. Have you seen my comment above? #83407 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hadn't, looking into it. (The parser is indeed not supposed to be able to use that to avoid diverging parsing based on feature gates.) |
||
let peeled = paren.peel_parens(); | ||
if let ExprKind::Let(_, _) = peeled.kind { | ||
// A user has written `if (let <pat> = <expr>)` (with some number of parens), we | ||
// want to avoid confusing them with mentions of nightly features. If this logic is | ||
// changed, you will also likely need to touch `unused::UnusedParens::check_expr`. | ||
self.if_let_expr_with_parens(&cond, peeled); | ||
cond = cond.peel_parens_owned(); | ||
} | ||
} | ||
|
||
let cond = P(cond); | ||
|
||
// Verify that the parsed `if` condition makes sense as a condition. If it is a block, then | ||
// verify that the last statement is either an implicit return (no `;`) or an explicit | ||
|
@@ -1794,6 +1807,22 @@ impl<'a> Parser<'a> { | |
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs)) | ||
} | ||
|
||
fn if_let_expr_with_parens(&mut self, cond: &Expr, paren: &Expr) { | ||
let start = cond.span.until(paren.span); | ||
let end = paren.span.shrink_to_hi().until(cond.span.shrink_to_hi()); | ||
self.struct_span_err( | ||
vec![start, end], | ||
"invalid parentheses around `let` expression in `if let`", | ||
) | ||
.multipart_suggestion( | ||
"`if let` needs to be written without parentheses", | ||
vec![(start, String::new()), (end, String::new())], | ||
rustc_errors::Applicability::MachineApplicable, | ||
) | ||
.emit(); | ||
self.sess.gated_spans.ungate_last(sym::let_chains, paren.span); | ||
} | ||
|
||
fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> { | ||
let sp = self.sess.source_map().next_point(lo); | ||
self.struct_span_err(sp, "missing condition for `if` expression") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the
into_inner
necessary? IIUC, you need that to be able to reassing, but wouldn't changing line 1777 to becond = P(cond.peel_parens_owned());
work as well and make this "unwrapping/rewrapping" unnecessary in the happy path? I'm just concerned about doing unnecessary work that might marginally slow down compile times.