@@ -63,7 +63,7 @@ use syntax::errors;
63
63
use syntax:: ext:: hygiene:: { Mark , SyntaxContext } ;
64
64
use syntax:: print:: pprust;
65
65
use syntax:: source_map:: { self , respan, ExpnInfo , CompilerDesugaringKind , Spanned } ;
66
- use syntax:: source_map:: CompilerDesugaringKind :: IfTemporary ;
66
+ use syntax:: source_map:: CompilerDesugaringKind :: CondTemporary ;
67
67
use syntax:: std_inject;
68
68
use syntax:: symbol:: { kw, sym, Symbol } ;
69
69
use syntax:: tokenstream:: { TokenStream , TokenTree } ;
@@ -4394,21 +4394,18 @@ impl<'a> LoweringContext<'a> {
4394
4394
let then_blk = self . lower_block ( then, false ) ;
4395
4395
let then_expr = self . expr_block ( then_blk, ThinVec :: new ( ) ) ;
4396
4396
let ( then_pats, scrutinee, desugar) = match cond. node {
4397
- // `<pat> => <then>`
4397
+ // `<pat> => <then>`:
4398
4398
ExprKind :: Let ( ref pats, ref scrutinee) => {
4399
4399
let scrutinee = self . lower_expr ( scrutinee) ;
4400
4400
let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
4401
4401
let desugar = hir:: MatchSource :: IfLetDesugar { contains_else_clause } ;
4402
4402
( pats, scrutinee, desugar)
4403
4403
}
4404
- // `true => then`:
4404
+ // `true => < then> `:
4405
4405
_ => {
4406
4406
// Lower condition:
4407
4407
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 ) ;
4412
4409
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
4413
4410
// to preserve drop semantics since `if cond { ... }` does not
4414
4411
// let temporaries live outside of `cond`.
@@ -4424,69 +4421,78 @@ impl<'a> LoweringContext<'a> {
4424
4421
hir:: ExprKind :: Match ( P ( scrutinee) , vec ! [ then_arm, else_arm] . into ( ) , desugar)
4425
4422
}
4426
4423
// 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.
4449
4427
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
+ } ;
4456
4434
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
+ // ```
4462
4464
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 ( ) ) ;
4470
4472
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
+ } ) ,
4490
4496
ExprKind :: Loop ( ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
4491
4497
hir:: ExprKind :: Loop (
4492
4498
this. lower_block ( body, false ) ,
0 commit comments