@@ -26,6 +26,7 @@ use rustc_macros::Subdiagnostic;
2626use rustc_session:: errors:: { ExprParenthesesNeeded , report_lit_error} ;
2727use rustc_session:: lint:: BuiltinLintDiag ;
2828use rustc_session:: lint:: builtin:: BREAK_WITH_LABEL_AND_LOOP ;
29+ use rustc_span:: edition:: Edition ;
2930use rustc_span:: source_map:: { self , Spanned } ;
3031use rustc_span:: { BytePos , ErrorGuaranteed , Ident , Pos , Span , Symbol , kw, sym} ;
3132use thin_vec:: { ThinVec , thin_vec} ;
@@ -2500,7 +2501,7 @@ impl<'a> Parser<'a> {
25002501 /// Parses an `if` expression (`if` token already eaten).
25012502 fn parse_expr_if ( & mut self ) -> PResult < ' a , P < Expr > > {
25022503 let lo = self . prev_token . span ;
2503- let cond = self . parse_expr_cond ( ) ?;
2504+ let cond = self . parse_expr_cond ( lo . edition ( ) ) ?;
25042505 self . parse_if_after_cond ( lo, cond)
25052506 }
25062507
@@ -2609,7 +2610,10 @@ impl<'a> Parser<'a> {
26092610 }
26102611
26112612 /// Parses the condition of a `if` or `while` expression.
2612- fn parse_expr_cond ( & mut self ) -> PResult < ' a , P < Expr > > {
2613+ ///
2614+ /// The specified `edition` should be that of the whole `if` or `while` construct: the same
2615+ /// span that we later decide the drop behaviour on (editions ..=2021 vs 2024..)
2616+ fn parse_expr_cond ( & mut self , edition : Edition ) -> PResult < ' a , P < Expr > > {
26132617 let attrs = self . parse_outer_attributes ( ) ?;
26142618 let ( mut cond, _) =
26152619 self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL | Restrictions :: ALLOW_LET , attrs) ?;
@@ -2619,6 +2623,27 @@ impl<'a> Parser<'a> {
26192623 if let ExprKind :: Let ( _, _, _, Recovered :: No ) = cond. kind {
26202624 // Remove the last feature gating of a `let` expression since it's stable.
26212625 self . psess . gated_spans . ungate_last ( sym:: let_chains, cond. span ) ;
2626+ } else {
2627+ fn ungate_let_exprs ( this : & mut Parser < ' _ > , expr : & Expr ) {
2628+ if !expr. span . at_least_rust_2024 ( ) {
2629+ return ;
2630+ }
2631+ match & expr. kind {
2632+ ExprKind :: Binary ( BinOp { node : BinOpKind :: And , .. } , lhs, rhs) => {
2633+ ungate_let_exprs ( this, rhs) ;
2634+ ungate_let_exprs ( this, lhs) ;
2635+ }
2636+ ExprKind :: Let ( ..) => {
2637+ this. psess . gated_spans . ungate_last ( sym:: let_chains, expr. span )
2638+ }
2639+ _ => ( ) ,
2640+ }
2641+ }
2642+ if edition. at_least_rust_2024 ( ) {
2643+ // Scoping code checks the top level edition of the `if`: let's match it here.
2644+ // Also check all editions in between, just to make sure.
2645+ ungate_let_exprs ( self , & cond) ;
2646+ }
26222647 }
26232648
26242649 Ok ( cond)
@@ -2910,7 +2935,7 @@ impl<'a> Parser<'a> {
29102935
29112936 /// Parses a `while` or `while let` expression (`while` token already eaten).
29122937 fn parse_expr_while ( & mut self , opt_label : Option < Label > , lo : Span ) -> PResult < ' a , P < Expr > > {
2913- let cond = self . parse_expr_cond ( ) . map_err ( |mut err| {
2938+ let cond = self . parse_expr_cond ( lo . edition ( ) ) . map_err ( |mut err| {
29142939 err. span_label ( lo, "while parsing the condition of this `while` expression" ) ;
29152940 err
29162941 } ) ?;
0 commit comments