diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3bd7aaee78e..20a5252624d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2606,7 +2606,10 @@ impl<'a> Parser<'a> { /// Parses an `if` expression (`if` token already eaten). fn parse_expr_if(&mut self) -> PResult<'a, P> { let lo = self.prev_token.span; - let cond = self.parse_expr_cond(lo.edition())?; + // Scoping code checks the top level edition of the `if`; let's match it here. + // The `CondChecker` also checks the edition of the `let` itself, just to make sure. + let let_chains_policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() }; + let cond = self.parse_expr_cond(let_chains_policy)?; self.parse_if_after_cond(lo, cond) } @@ -2716,41 +2719,16 @@ impl<'a> Parser<'a> { /// Parses the condition of a `if` or `while` expression. /// - /// The specified `edition` should be that of the whole `if` or `while` construct: the same - /// span that we later decide the drop behaviour on (editions ..=2021 vs 2024..) + /// The specified `edition` in `let_chains_policy` should be that of the whole `if` construct, + /// i.e. the same span we use to later decide whether the drop behaviour should be that of + /// edition `..=2021` or that of `2024..`. // Public because it is used in rustfmt forks such as https://github.com/tucant/rustfmt/blob/30c83df9e1db10007bdd16dafce8a86b404329b2/src/parse/macros/html.rs#L57 for custom if expressions. - pub fn parse_expr_cond(&mut self, edition: Edition) -> PResult<'a, P> { + pub fn parse_expr_cond(&mut self, let_chains_policy: LetChainsPolicy) -> PResult<'a, P> { let attrs = self.parse_outer_attributes()?; let (mut cond, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?; - CondChecker::new(self).visit_expr(&mut cond); - - if let ExprKind::Let(_, _, _, Recovered::No) = cond.kind { - // Remove the last feature gating of a `let` expression since it's stable. - self.psess.gated_spans.ungate_last(sym::let_chains, cond.span); - } else { - fn ungate_let_exprs(this: &mut Parser<'_>, expr: &Expr) { - if !expr.span.at_least_rust_2024() { - return; - } - match &expr.kind { - ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => { - ungate_let_exprs(this, rhs); - ungate_let_exprs(this, lhs); - } - ExprKind::Let(..) => { - this.psess.gated_spans.ungate_last(sym::let_chains, expr.span) - } - _ => (), - } - } - if edition.at_least_rust_2024() { - // Scoping code checks the top level edition of the `if`: let's match it here. - // Also check all editions in between, just to make sure. - ungate_let_exprs(self, &cond); - } - } + CondChecker::new(self, let_chains_policy).visit_expr(&mut cond); Ok(cond) } @@ -3045,7 +3023,8 @@ impl<'a> Parser<'a> { /// Parses a `while` or `while let` expression (`while` token already eaten). fn parse_expr_while(&mut self, opt_label: Option