@@ -25,6 +25,7 @@ use rustc_macros::Subdiagnostic;
25
25
use rustc_session:: errors:: { ExprParenthesesNeeded , report_lit_error} ;
26
26
use rustc_session:: lint:: BuiltinLintDiag ;
27
27
use rustc_session:: lint:: builtin:: BREAK_WITH_LABEL_AND_LOOP ;
28
+ use rustc_span:: edition:: Edition ;
28
29
use rustc_span:: source_map:: { self , Spanned } ;
29
30
use rustc_span:: symbol:: { Ident , Symbol , kw, sym} ;
30
31
use rustc_span:: { BytePos , ErrorGuaranteed , Pos , Span } ;
@@ -2486,7 +2487,7 @@ impl<'a> Parser<'a> {
2486
2487
/// Parses an `if` expression (`if` token already eaten).
2487
2488
fn parse_expr_if ( & mut self ) -> PResult < ' a , P < Expr > > {
2488
2489
let lo = self . prev_token . span ;
2489
- let cond = self . parse_expr_cond ( ) ?;
2490
+ let cond = self . parse_expr_cond ( lo . edition ( ) ) ?;
2490
2491
self . parse_if_after_cond ( lo, cond)
2491
2492
}
2492
2493
@@ -2595,7 +2596,10 @@ impl<'a> Parser<'a> {
2595
2596
}
2596
2597
2597
2598
/// Parses the condition of a `if` or `while` expression.
2598
- fn parse_expr_cond ( & mut self ) -> PResult < ' a , P < Expr > > {
2599
+ ///
2600
+ /// The specified `edition` should be that of the whole `if` or `while` construct: the same
2601
+ /// span that we later decide the drop behaviour on (editions ..=2021 vs 2024..)
2602
+ fn parse_expr_cond ( & mut self , edition : Edition ) -> PResult < ' a , P < Expr > > {
2599
2603
let attrs = self . parse_outer_attributes ( ) ?;
2600
2604
let ( mut cond, _) =
2601
2605
self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL | Restrictions :: ALLOW_LET , attrs) ?;
@@ -2605,6 +2609,27 @@ impl<'a> Parser<'a> {
2605
2609
if let ExprKind :: Let ( _, _, _, Recovered :: No ) = cond. kind {
2606
2610
// Remove the last feature gating of a `let` expression since it's stable.
2607
2611
self . psess . gated_spans . ungate_last ( sym:: let_chains, cond. span ) ;
2612
+ } else {
2613
+ fn ungate_let_exprs ( this : & mut Parser < ' _ > , expr : & Expr ) {
2614
+ if !expr. span . at_least_rust_2024 ( ) {
2615
+ return ;
2616
+ }
2617
+ match & expr. kind {
2618
+ ExprKind :: Binary ( BinOp { node : BinOpKind :: And , .. } , lhs, rhs) => {
2619
+ ungate_let_exprs ( this, rhs) ;
2620
+ ungate_let_exprs ( this, lhs) ;
2621
+ }
2622
+ ExprKind :: Let ( ..) => {
2623
+ this. psess . gated_spans . ungate_last ( sym:: let_chains, expr. span )
2624
+ }
2625
+ _ => ( ) ,
2626
+ }
2627
+ }
2628
+ if edition. at_least_rust_2024 ( ) {
2629
+ // Scoping code checks the top level edition of the `if`: let's match it here.
2630
+ // Also check all editions in between, just to make sure.
2631
+ ungate_let_exprs ( self , & cond) ;
2632
+ }
2608
2633
}
2609
2634
2610
2635
Ok ( cond)
@@ -2889,7 +2914,7 @@ impl<'a> Parser<'a> {
2889
2914
2890
2915
/// Parses a `while` or `while let` expression (`while` token already eaten).
2891
2916
fn parse_expr_while ( & mut self , opt_label : Option < Label > , lo : Span ) -> PResult < ' a , P < Expr > > {
2892
- let cond = self . parse_expr_cond ( ) . map_err ( |mut err| {
2917
+ let cond = self . parse_expr_cond ( lo . edition ( ) ) . map_err ( |mut err| {
2893
2918
err. span_label ( lo, "while parsing the condition of this `while` expression" ) ;
2894
2919
err
2895
2920
} ) ?;
0 commit comments