@@ -63,7 +63,7 @@ use syntax::errors;
6363use syntax:: ext:: hygiene:: { Mark , SyntaxContext } ;
6464use syntax:: print:: pprust;
6565use syntax:: source_map:: { self , respan, ExpnInfo , CompilerDesugaringKind , Spanned } ;
66- use syntax:: source_map:: CompilerDesugaringKind :: IfTemporary ;
66+ use syntax:: source_map:: CompilerDesugaringKind :: CondTemporary ;
6767use syntax:: std_inject;
6868use syntax:: symbol:: { kw, sym, Symbol } ;
6969use syntax:: tokenstream:: { TokenStream , TokenTree } ;
@@ -4394,21 +4394,18 @@ impl<'a> LoweringContext<'a> {
43944394 let then_blk = self . lower_block ( then, false ) ;
43954395 let then_expr = self . expr_block ( then_blk, ThinVec :: new ( ) ) ;
43964396 let ( then_pats, scrutinee, desugar) = match cond. node {
4397- // `<pat> => <then>`
4397+ // `<pat> => <then>`:
43984398 ExprKind :: Let ( ref pats, ref scrutinee) => {
43994399 let scrutinee = self . lower_expr ( scrutinee) ;
44004400 let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
44014401 let desugar = hir:: MatchSource :: IfLetDesugar { contains_else_clause } ;
44024402 ( pats, scrutinee, desugar)
44034403 }
4404- // `true => then`:
4404+ // `true => < then> `:
44054405 _ => {
44064406 // Lower condition:
44074407 let cond = self . lower_expr ( cond) ;
4408- // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
4409- // to preserve drop semantics since `if cond { ... }`
4410- // don't let temporaries live outside of `cond`.
4411- let span_block = self . mark_span_with_reason ( IfTemporary , cond. span , None ) ;
4408+ let span_block = self . mark_span_with_reason ( CondTemporary , cond. span , None ) ;
44124409 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
44134410 // to preserve drop semantics since `if cond { ... }` does not
44144411 // let temporaries live outside of `cond`.
@@ -4424,69 +4421,78 @@ impl<'a> LoweringContext<'a> {
44244421 hir:: ExprKind :: Match ( P ( scrutinee) , vec ! [ then_arm, else_arm] . into ( ) , desugar)
44254422 }
44264423 // FIXME(#53667): handle lowering of && and parens.
4427- ExprKind :: While ( ref cond, ref body, opt_label) => {
4428- // Desugar `ExprWhileLet`
4429- // from: `[opt_ident]: while let <pat> = <sub_expr> <body>`
4430- if let ExprKind :: Let ( ref pats, ref sub_expr) = cond. node {
4431- // to:
4432- //
4433- // [opt_ident]: loop {
4434- // match <sub_expr> {
4435- // <pat> => <body>,
4436- // _ => break
4437- // }
4438- // }
4439-
4440- // Note that the block AND the condition are evaluated in the loop scope.
4441- // This is done to allow `break` from inside the condition of the loop.
4442- let ( body, break_expr, sub_expr) = self . with_loop_scope ( e. id , |this| {
4443- (
4444- this. lower_block ( body, false ) ,
4445- this. expr_break ( e. span , ThinVec :: new ( ) ) ,
4446- this. with_loop_condition_scope ( |this| P ( this. lower_expr ( sub_expr) ) ) ,
4447- )
4448- } ) ;
4424+ ExprKind :: While ( ref cond, ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
4425+ // Note that the block AND the condition are evaluated in the loop scope.
4426+ // This is done to allow `break` from inside the condition of the loop.
44494427
4450- // `<pat> => <body>`
4451- let pat_arm = {
4452- let body_expr = P ( self . expr_block ( body , ThinVec :: new ( ) ) ) ;
4453- let pats = pats . iter ( ) . map ( |pat| self . lower_pat ( pat ) ) . collect ( ) ;
4454- self . arm ( pats , body_expr )
4455- } ;
4428+ // `_ => break`:
4429+ let else_arm = {
4430+ let else_pat = this . pat_wild ( e . span ) ;
4431+ let else_expr = this . expr_break ( e . span , ThinVec :: new ( ) ) ;
4432+ this . arm ( hir_vec ! [ else_pat ] , else_expr )
4433+ } ;
44564434
4457- // `_ => break`
4458- let break_arm = {
4459- let pat_under = self . pat_wild ( e. span ) ;
4460- self . arm ( hir_vec ! [ pat_under] , break_expr)
4461- } ;
4435+ // Handle then + scrutinee:
4436+ let then_blk = this. lower_block ( body, false ) ;
4437+ let then_expr = this. expr_block ( then_blk, ThinVec :: new ( ) ) ;
4438+ let ( then_pats, scrutinee, desugar, source) = match cond. node {
4439+ ExprKind :: Let ( ref pats, ref scrutinee) => {
4440+ // to:
4441+ //
4442+ // [opt_ident]: loop {
4443+ // match <sub_expr> {
4444+ // <pat> => <body>,
4445+ // _ => break
4446+ // }
4447+ // }
4448+ let scrutinee = this. with_loop_condition_scope ( |t| t. lower_expr ( scrutinee) ) ;
4449+ let pats = pats. iter ( ) . map ( |pat| this. lower_pat ( pat) ) . collect ( ) ;
4450+ let desugar = hir:: MatchSource :: WhileLetDesugar ;
4451+ ( pats, scrutinee, desugar, hir:: LoopSource :: WhileLet )
4452+ }
4453+ _ => {
4454+ // We desugar: `'label: while $cond $body` into:
4455+ //
4456+ // ```
4457+ // 'label: loop {
4458+ // match DropTemps($cond) {
4459+ // true => $body,
4460+ // _ => break,
4461+ // }
4462+ // }
4463+ // ```
44624464
4463- // `match <sub_expr> { ... }`
4464- let arms = hir_vec ! [ pat_arm , break_arm ] ;
4465- let match_expr = self . expr (
4466- sub_expr . span ,
4467- hir :: ExprKind :: Match ( sub_expr , arms , hir :: MatchSource :: WhileLetDesugar ) ,
4468- ThinVec :: new ( ) ,
4469- ) ;
4465+ // Lower condition:
4466+ let cond = this . with_loop_condition_scope ( |this| this . lower_expr ( cond ) ) ;
4467+ let span_block = this . mark_span_with_reason ( CondTemporary , cond . span , None ) ;
4468+ // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
4469+ // to preserve drop semantics since `while cond { ... }` does not
4470+ // let temporaries live outside of `cond`.
4471+ let cond = this . expr_drop_temps ( span_block , P ( cond ) , ThinVec :: new ( ) ) ;
44704472
4471- // `[opt_ident]: loop { ... }`
4472- let loop_block = P ( self . block_expr ( P ( match_expr) ) ) ;
4473- let loop_expr = hir:: ExprKind :: Loop (
4474- loop_block,
4475- self . lower_label ( opt_label) ,
4476- hir:: LoopSource :: WhileLet ,
4477- ) ;
4478- // Add attributes to the outer returned expr node.
4479- loop_expr
4480- } else {
4481- self . with_loop_scope ( e. id , |this| {
4482- hir:: ExprKind :: While (
4483- this. with_loop_condition_scope ( |this| P ( this. lower_expr ( cond) ) ) ,
4484- this. lower_block ( body, false ) ,
4485- this. lower_label ( opt_label) ,
4486- )
4487- } )
4488- }
4489- }
4473+ let desugar = hir:: MatchSource :: WhileDesugar ;
4474+ // `true => <then>`:
4475+ let pats = hir_vec ! [ this. pat_bool( e. span, true ) ] ;
4476+ ( pats, cond, desugar, hir:: LoopSource :: While )
4477+ }
4478+ } ;
4479+ let then_arm = this. arm ( then_pats, P ( then_expr) ) ;
4480+
4481+ // `match <scrutinee> { ... }`
4482+ let match_expr = this. expr_match (
4483+ scrutinee. span ,
4484+ P ( scrutinee) ,
4485+ hir_vec ! [ then_arm, else_arm] ,
4486+ desugar,
4487+ ) ;
4488+
4489+ // `[opt_ident]: loop { ... }`
4490+ hir:: ExprKind :: Loop (
4491+ P ( this. block_expr ( P ( match_expr) ) ) ,
4492+ this. lower_label ( opt_label) ,
4493+ source
4494+ )
4495+ } ) ,
44904496 ExprKind :: Loop ( ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
44914497 hir:: ExprKind :: Loop (
44924498 this. lower_block ( body, false ) ,
0 commit comments