diff options
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 31 | ||||
| -rw-r--r-- | tests/ui/drop/drop_order.rs | 3 | ||||
| -rw-r--r-- | tests/ui/drop/drop_order_if_let_rescope.rs | 4 | ||||
| -rw-r--r-- | tests/ui/drop/issue-100276.rs | 7 | ||||
| -rw-r--r-- | tests/ui/mir/mir_let_chains_drop_order.rs | 2 |
5 files changed, 38 insertions, 9 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index df44b3cc23c..e60912d85b7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -26,6 +26,7 @@ use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; +use rustc_span::edition::Edition; use rustc_span::source_map::{self, Spanned}; use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Symbol, kw, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -2605,7 +2606,7 @@ impl<'a> Parser<'a> { /// Parses an `if` expression (`if` token already eaten). fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> { let lo = self.prev_token.span; - let cond = self.parse_expr_cond()?; + let cond = self.parse_expr_cond(lo.edition())?; self.parse_if_after_cond(lo, cond) } @@ -2714,8 +2715,11 @@ 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..) // 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) -> PResult<'a, P<Expr>> { + pub fn parse_expr_cond(&mut self, edition: Edition) -> PResult<'a, P<Expr>> { let attrs = self.parse_outer_attributes()?; let (mut cond, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?; @@ -2725,6 +2729,27 @@ impl<'a> Parser<'a> { 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); + } } Ok(cond) @@ -3020,7 +3045,7 @@ impl<'a> Parser<'a> { /// Parses a `while` or `while let` expression (`while` token already eaten). fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { - let cond = self.parse_expr_cond().map_err(|mut err| { + let cond = self.parse_expr_cond(lo.edition()).map_err(|mut err| { err.span_label(lo, "while parsing the condition of this `while` expression"); err })?; diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index d1a5b9bc5e2..b96e55a2535 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -2,9 +2,10 @@ //@ compile-flags: -Z validate-mir //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 +//@ [edition2024] compile-flags: -Z lint-mir //@ [edition2024] edition: 2024 -#![feature(let_chains)] +#![cfg_attr(edition2021, feature(let_chains))] use std::cell::RefCell; use std::convert::TryInto; diff --git a/tests/ui/drop/drop_order_if_let_rescope.rs b/tests/ui/drop/drop_order_if_let_rescope.rs index 7445e3a6a5f..27bced5fa62 100644 --- a/tests/ui/drop/drop_order_if_let_rescope.rs +++ b/tests/ui/drop/drop_order_if_let_rescope.rs @@ -1,8 +1,6 @@ //@ run-pass //@ edition:2024 -//@ compile-flags: -Z validate-mir - -#![feature(let_chains)] +//@ compile-flags: -Z validate-mir -Z lint-mir use std::cell::RefCell; use std::convert::TryInto; diff --git a/tests/ui/drop/issue-100276.rs b/tests/ui/drop/issue-100276.rs index b44710e7c3f..5d212b3a0a9 100644 --- a/tests/ui/drop/issue-100276.rs +++ b/tests/ui/drop/issue-100276.rs @@ -1,6 +1,11 @@ //@ check-pass //@ compile-flags: -Z validate-mir -#![feature(let_chains)] +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] compile-flags: -Z lint-mir +//@ [edition2024] edition: 2024 + +#![cfg_attr(edition2021, feature(let_chains))] fn let_chains(entry: std::io::Result<std::fs::DirEntry>) { if let Ok(entry) = entry diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs index 8991c6db7b9..4794f3427dd 100644 --- a/tests/ui/mir/mir_let_chains_drop_order.rs +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -6,7 +6,7 @@ // See `mir_drop_order.rs` for more information -#![feature(let_chains)] +#![cfg_attr(edition2021, feature(let_chains))] #![allow(irrefutable_let_patterns)] use std::cell::RefCell; |
