Skip to content

Commit 0397071

Browse files
committed
Stabilize let chains on edition 2024
1 parent 9f274ba commit 0397071

File tree

5 files changed

+38
-9
lines changed

5 files changed

+38
-9
lines changed

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rustc_macros::Subdiagnostic;
2626
use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error};
2727
use rustc_session::lint::BuiltinLintDiag;
2828
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
29+
use rustc_span::edition::Edition;
2930
use rustc_span::source_map::{self, Spanned};
3031
use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Symbol, kw, sym};
3132
use thin_vec::{ThinVec, thin_vec};
@@ -2479,7 +2480,7 @@ impl<'a> Parser<'a> {
24792480
/// Parses an `if` expression (`if` token already eaten).
24802481
fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
24812482
let lo = self.prev_token.span;
2482-
let cond = self.parse_expr_cond()?;
2483+
let cond = self.parse_expr_cond(lo.edition())?;
24832484
self.parse_if_after_cond(lo, cond)
24842485
}
24852486

@@ -2588,8 +2589,11 @@ impl<'a> Parser<'a> {
25882589
}
25892590

25902591
/// Parses the condition of a `if` or `while` expression.
2592+
///
2593+
/// The specified `edition` should be that of the whole `if` or `while` construct: the same
2594+
/// span that we later decide the drop behaviour on (editions ..=2021 vs 2024..)
25912595
// 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.
2592-
pub fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
2596+
pub fn parse_expr_cond(&mut self, edition: Edition) -> PResult<'a, P<Expr>> {
25932597
let attrs = self.parse_outer_attributes()?;
25942598
let (mut cond, _) =
25952599
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?;
@@ -2599,6 +2603,27 @@ impl<'a> Parser<'a> {
25992603
if let ExprKind::Let(_, _, _, Recovered::No) = cond.kind {
26002604
// Remove the last feature gating of a `let` expression since it's stable.
26012605
self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
2606+
} else {
2607+
fn ungate_let_exprs(this: &mut Parser<'_>, expr: &Expr) {
2608+
if !expr.span.at_least_rust_2024() {
2609+
return;
2610+
}
2611+
match &expr.kind {
2612+
ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => {
2613+
ungate_let_exprs(this, rhs);
2614+
ungate_let_exprs(this, lhs);
2615+
}
2616+
ExprKind::Let(..) => {
2617+
this.psess.gated_spans.ungate_last(sym::let_chains, expr.span)
2618+
}
2619+
_ => (),
2620+
}
2621+
}
2622+
if edition.at_least_rust_2024() {
2623+
// Scoping code checks the top level edition of the `if`: let's match it here.
2624+
// Also check all editions in between, just to make sure.
2625+
ungate_let_exprs(self, &cond);
2626+
}
26022627
}
26032628

26042629
Ok(cond)
@@ -2890,7 +2915,7 @@ impl<'a> Parser<'a> {
28902915

28912916
/// Parses a `while` or `while let` expression (`while` token already eaten).
28922917
fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2893-
let cond = self.parse_expr_cond().map_err(|mut err| {
2918+
let cond = self.parse_expr_cond(lo.edition()).map_err(|mut err| {
28942919
err.span_label(lo, "while parsing the condition of this `while` expression");
28952920
err
28962921
})?;

tests/ui/drop/drop_order.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
//@ compile-flags: -Z validate-mir
33
//@ revisions: edition2021 edition2024
44
//@ [edition2021] edition: 2021
5+
//@ [edition2024] compile-flags: -Z lint-mir
56
//@ [edition2024] edition: 2024
67

7-
#![feature(let_chains)]
8+
#![cfg_attr(edition2021, feature(let_chains))]
89

910
use std::cell::RefCell;
1011
use std::convert::TryInto;

tests/ui/drop/drop_order_if_let_rescope.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//@ run-pass
22
//@ edition:2024
3-
//@ compile-flags: -Z validate-mir
4-
5-
#![feature(let_chains)]
3+
//@ compile-flags: -Z validate-mir -Z lint-mir
64

75
use std::cell::RefCell;
86
use std::convert::TryInto;

tests/ui/drop/issue-100276.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//@ check-pass
22
//@ compile-flags: -Z validate-mir
3-
#![feature(let_chains)]
3+
//@ revisions: edition2021 edition2024
4+
//@ [edition2021] edition: 2021
5+
//@ [edition2024] compile-flags: -Z lint-mir
6+
//@ [edition2024] edition: 2024
7+
8+
#![cfg_attr(edition2021, feature(let_chains))]
49

510
fn let_chains(entry: std::io::Result<std::fs::DirEntry>) {
611
if let Ok(entry) = entry

tests/ui/mir/mir_let_chains_drop_order.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
// See `mir_drop_order.rs` for more information
88

9-
#![feature(let_chains)]
9+
#![cfg_attr(edition2021, feature(let_chains))]
1010
#![allow(irrefutable_let_patterns)]
1111

1212
use std::cell::RefCell;

0 commit comments

Comments
 (0)