@@ -62,6 +62,7 @@ use syntax::ext::hygiene::Mark;
62
62
use syntax:: print:: pprust;
63
63
use syntax:: ptr:: P ;
64
64
use syntax:: source_map:: { respan, CompilerDesugaringKind , Spanned } ;
65
+ use syntax:: source_map:: CompilerDesugaringKind :: IfTemporary ;
65
66
use syntax:: std_inject;
66
67
use syntax:: symbol:: { keywords, Symbol } ;
67
68
use syntax:: tokenstream:: { TokenStream , TokenTree } ;
@@ -4115,31 +4116,46 @@ impl<'a> LoweringContext<'a> {
4115
4116
}
4116
4117
// More complicated than you might expect because the else branch
4117
4118
// might be `if let`.
4118
- ExprKind :: If ( ref cond, ref blk, ref else_opt) => {
4119
- let else_opt = else_opt. as_ref ( ) . map ( |els| {
4120
- match els. node {
4119
+ ExprKind :: If ( ref cond, ref then, ref else_opt) => {
4120
+ // `true => then`:
4121
+ let then_pat = self . pat_bool ( e. span , true ) ;
4122
+ let then_blk = self . lower_block ( then, false ) ;
4123
+ let then_expr = self . expr_block ( then_blk, ThinVec :: new ( ) ) ;
4124
+ let then_arm = self . arm ( hir_vec ! [ then_pat] , P ( then_expr) ) ;
4125
+
4126
+ // `_ => else_block` where `else_block` is `{}` if there's `None`:
4127
+ let else_pat = self . pat_wild ( e. span ) ;
4128
+ let else_expr = match else_opt {
4129
+ None => self . expr_block_empty ( e. span ) ,
4130
+ Some ( els) => match els. node {
4121
4131
ExprKind :: IfLet ( ..) => {
4122
4132
// Wrap the `if let` expr in a block.
4123
- let span = els. span ;
4124
- let els = P ( self . lower_expr ( els) ) ;
4125
- let blk = P ( hir:: Block {
4126
- stmts : hir_vec ! [ ] ,
4127
- expr : Some ( els) ,
4128
- hir_id : self . next_id ( ) ,
4129
- rules : hir:: DefaultBlock ,
4130
- span,
4131
- targeted_by_break : false ,
4132
- } ) ;
4133
- P ( self . expr_block ( blk, ThinVec :: new ( ) ) )
4133
+ let els = self . lower_expr ( els) ;
4134
+ let blk = self . block_all ( els. span , hir_vec ! [ ] , Some ( P ( els) ) ) ;
4135
+ self . expr_block ( P ( blk) , ThinVec :: new ( ) )
4134
4136
}
4135
- _ => P ( self . lower_expr ( els) ) ,
4137
+ _ => self . lower_expr ( els) ,
4136
4138
}
4137
- } ) ;
4138
-
4139
- let then_blk = self . lower_block ( blk, false ) ;
4140
- let then_expr = self . expr_block ( then_blk, ThinVec :: new ( ) ) ;
4139
+ } ;
4140
+ let else_arm = self . arm ( hir_vec ! [ else_pat] , P ( else_expr) ) ;
4141
+
4142
+ // Lower condition:
4143
+ let span_block = self
4144
+ . sess
4145
+ . source_map ( )
4146
+ . mark_span_with_reason ( IfTemporary , cond. span , None ) ;
4147
+ let cond = self . lower_expr ( cond) ;
4148
+ // Wrap in a construct equivalent to `{ let _t = $cond; _t }` to preserve drop
4149
+ // semantics since `if cond { ... }` don't let temporaries live outside of `cond`.
4150
+ let cond = self . expr_drop_temps ( span_block, P ( cond) , ThinVec :: new ( ) ) ;
4141
4151
4142
- hir:: ExprKind :: If ( P ( self . lower_expr ( cond) ) , P ( then_expr) , else_opt)
4152
+ hir:: ExprKind :: Match (
4153
+ P ( cond) ,
4154
+ vec ! [ then_arm, else_arm] . into ( ) ,
4155
+ hir:: MatchSource :: IfDesugar {
4156
+ contains_else_clause : else_opt. is_some ( )
4157
+ } ,
4158
+ )
4143
4159
}
4144
4160
ExprKind :: While ( ref cond, ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
4145
4161
hir:: ExprKind :: While (
@@ -4486,16 +4502,16 @@ impl<'a> LoweringContext<'a> {
4486
4502
arms. push ( self . arm ( pats, body_expr) ) ;
4487
4503
}
4488
4504
4489
- // _ => [<else_opt>|() ]
4505
+ // _ => [<else_opt>|{} ]
4490
4506
{
4491
4507
let wildcard_arm: Option < & Expr > = else_opt. as_ref ( ) . map ( |p| & * * p) ;
4492
4508
let wildcard_pattern = self . pat_wild ( e. span ) ;
4493
4509
let body = if let Some ( else_expr) = wildcard_arm {
4494
- P ( self . lower_expr ( else_expr) )
4510
+ self . lower_expr ( else_expr)
4495
4511
} else {
4496
- P ( self . expr_tuple ( e. span , hir_vec ! [ ] ) )
4512
+ self . expr_block_empty ( e. span )
4497
4513
} ;
4498
- arms. push ( self . arm ( hir_vec ! [ wildcard_pattern] , body) ) ;
4514
+ arms. push ( self . arm ( hir_vec ! [ wildcard_pattern] , P ( body) ) ) ;
4499
4515
}
4500
4516
4501
4517
let contains_else_clause = else_opt. is_some ( ) ;
@@ -4658,11 +4674,7 @@ impl<'a> LoweringContext<'a> {
4658
4674
ThinVec :: new ( ) ,
4659
4675
) )
4660
4676
} ;
4661
- let match_stmt = hir:: Stmt {
4662
- hir_id : self . next_id ( ) ,
4663
- node : hir:: StmtKind :: Expr ( match_expr) ,
4664
- span : head_sp,
4665
- } ;
4677
+ let match_stmt = self . stmt ( head_sp, hir:: StmtKind :: Expr ( match_expr) ) ;
4666
4678
4667
4679
let next_expr = P ( self . expr_ident ( head_sp, next_ident, next_pat_hid) ) ;
4668
4680
@@ -4685,11 +4697,7 @@ impl<'a> LoweringContext<'a> {
4685
4697
4686
4698
let body_block = self . with_loop_scope ( e. id , |this| this. lower_block ( body, false ) ) ;
4687
4699
let body_expr = P ( self . expr_block ( body_block, ThinVec :: new ( ) ) ) ;
4688
- let body_stmt = hir:: Stmt {
4689
- hir_id : self . next_id ( ) ,
4690
- node : hir:: StmtKind :: Expr ( body_expr) ,
4691
- span : body. span ,
4692
- } ;
4700
+ let body_stmt = self . stmt ( body. span , hir:: StmtKind :: Expr ( body_expr) ) ;
4693
4701
4694
4702
let loop_block = P ( self . block_all (
4695
4703
e. span ,
@@ -4869,12 +4877,7 @@ impl<'a> LoweringContext<'a> {
4869
4877
. into_iter( )
4870
4878
. map( |item_id| {
4871
4879
let item_id = hir:: ItemId { id: self . lower_node_id( item_id) } ;
4872
-
4873
- hir:: Stmt {
4874
- hir_id: self . next_id( ) ,
4875
- node: hir:: StmtKind :: Item ( item_id) ,
4876
- span: s. span,
4877
- }
4880
+ self . stmt( s. span, hir:: StmtKind :: Item ( item_id) )
4878
4881
} )
4879
4882
. collect( ) ;
4880
4883
ids. push( {
@@ -5174,28 +5177,32 @@ impl<'a> LoweringContext<'a> {
5174
5177
}
5175
5178
}
5176
5179
5180
+ fn stmt ( & mut self , span : Span , node : hir:: StmtKind ) -> hir:: Stmt {
5181
+ hir:: Stmt { span, node, hir_id : self . next_id ( ) }
5182
+ }
5183
+
5177
5184
fn stmt_let_pat (
5178
5185
& mut self ,
5179
- sp : Span ,
5180
- ex : Option < P < hir:: Expr > > ,
5186
+ span : Span ,
5187
+ init : Option < P < hir:: Expr > > ,
5181
5188
pat : P < hir:: Pat > ,
5182
5189
source : hir:: LocalSource ,
5183
5190
) -> hir:: Stmt {
5184
5191
let local = hir:: Local {
5185
5192
pat,
5186
5193
ty : None ,
5187
- init : ex ,
5194
+ init,
5188
5195
hir_id : self . next_id ( ) ,
5189
- span : sp,
5190
- attrs : ThinVec :: new ( ) ,
5196
+ span,
5191
5197
source,
5198
+ attrs : ThinVec :: new ( )
5192
5199
} ;
5200
+ self . stmt ( span, hir:: StmtKind :: Local ( P ( local) ) )
5201
+ }
5193
5202
5194
- hir:: Stmt {
5195
- hir_id : self . next_id ( ) ,
5196
- node : hir:: StmtKind :: Local ( P ( local) ) ,
5197
- span : sp
5198
- }
5203
+ fn expr_block_empty ( & mut self , span : Span ) -> hir:: Expr {
5204
+ let blk = self . block_all ( span, hir_vec ! [ ] , None ) ;
5205
+ self . expr_block ( P ( blk) , ThinVec :: new ( ) )
5199
5206
}
5200
5207
5201
5208
fn block_expr ( & mut self , expr : P < hir:: Expr > ) -> hir:: Block {
@@ -5235,6 +5242,13 @@ impl<'a> LoweringContext<'a> {
5235
5242
)
5236
5243
}
5237
5244
5245
+ /// Constructs a `true` or `false` literal pattern.
5246
+ fn pat_bool ( & mut self , span : Span , val : bool ) -> P < hir:: Pat > {
5247
+ let lit = Spanned { span, node : LitKind :: Bool ( val) } ;
5248
+ let expr = self . expr ( span, hir:: ExprKind :: Lit ( lit) , ThinVec :: new ( ) ) ;
5249
+ self . pat ( span, hir:: PatKind :: Lit ( P ( expr) ) )
5250
+ }
5251
+
5238
5252
fn pat_ok ( & mut self , span : Span , pat : P < hir:: Pat > ) -> P < hir:: Pat > {
5239
5253
self . pat_std_enum ( span, & [ "result" , "Result" , "Ok" ] , hir_vec ! [ pat] )
5240
5254
}
@@ -5622,15 +5636,7 @@ impl<'a> LoweringContext<'a> {
5622
5636
& [ "task" , "Poll" , "Pending" ] ,
5623
5637
hir_vec ! [ ] ,
5624
5638
) ;
5625
- let empty_block = P ( hir:: Block {
5626
- stmts : hir_vec ! [ ] ,
5627
- expr : None ,
5628
- hir_id : self . next_id ( ) ,
5629
- rules : hir:: DefaultBlock ,
5630
- span,
5631
- targeted_by_break : false ,
5632
- } ) ;
5633
- let empty_block = P ( self . expr_block ( empty_block, ThinVec :: new ( ) ) ) ;
5639
+ let empty_block = P ( self . expr_block_empty ( span) ) ;
5634
5640
self . arm ( hir_vec ! [ pending_pat] , empty_block)
5635
5641
} ;
5636
5642
0 commit comments