@@ -25,6 +25,7 @@ use rustc_macros::Subdiagnostic;
2525use rustc_session:: errors:: { ExprParenthesesNeeded , report_lit_error} ;
2626use rustc_session:: lint:: BuiltinLintDiag ;
2727use rustc_session:: lint:: builtin:: BREAK_WITH_LABEL_AND_LOOP ;
28+ use rustc_span:: edition:: Edition ;
2829use rustc_span:: source_map:: { self , Spanned } ;
2930use rustc_span:: symbol:: { Ident , Symbol , kw, sym} ;
3031use rustc_span:: { BytePos , ErrorGuaranteed , Pos , Span } ;
@@ -2486,7 +2487,7 @@ impl<'a> Parser<'a> {
24862487 /// Parses an `if` expression (`if` token already eaten).
24872488 fn parse_expr_if ( & mut self ) -> PResult < ' a , P < Expr > > {
24882489 let lo = self . prev_token . span ;
2489- let cond = self . parse_expr_cond ( ) ?;
2490+ let cond = self . parse_expr_cond ( lo . edition ( ) ) ?;
24902491 self . parse_if_after_cond ( lo, cond)
24912492 }
24922493
@@ -2595,7 +2596,10 @@ impl<'a> Parser<'a> {
25952596 }
25962597
25972598 /// 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 > > {
25992603 let attrs = self . parse_outer_attributes ( ) ?;
26002604 let ( mut cond, _) =
26012605 self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL | Restrictions :: ALLOW_LET , attrs) ?;
@@ -2605,6 +2609,27 @@ impl<'a> Parser<'a> {
26052609 if let ExprKind :: Let ( _, _, _, Recovered :: No ) = cond. kind {
26062610 // Remove the last feature gating of a `let` expression since it's stable.
26072611 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+ }
26082633 }
26092634
26102635 Ok ( cond)
@@ -2889,7 +2914,7 @@ impl<'a> Parser<'a> {
28892914
28902915 /// Parses a `while` or `while let` expression (`while` token already eaten).
28912916 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| {
28932918 err. span_label ( lo, "while parsing the condition of this `while` expression" ) ;
28942919 err
28952920 } ) ?;
0 commit comments