@@ -62,6 +62,7 @@ use syntax::ext::hygiene::Mark;
6262use syntax:: print:: pprust;
6363use syntax:: ptr:: P ;
6464use syntax:: source_map:: { respan, CompilerDesugaringKind , Spanned } ;
65+ use syntax:: source_map:: CompilerDesugaringKind :: IfTemporary ;
6566use syntax:: std_inject;
6667use syntax:: symbol:: { keywords, Symbol } ;
6768use syntax:: tokenstream:: { TokenStream , TokenTree } ;
@@ -4115,31 +4116,46 @@ impl<'a> LoweringContext<'a> {
41154116 }
41164117 // More complicated than you might expect because the else branch
41174118 // 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 {
41214131 ExprKind :: IfLet ( ..) => {
41224132 // 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 ( ) )
41344136 }
4135- _ => P ( self . lower_expr ( els) ) ,
4137+ _ => self . lower_expr ( els) ,
41364138 }
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 ( ) ) ;
41414151
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+ )
41434159 }
41444160 ExprKind :: While ( ref cond, ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
41454161 hir:: ExprKind :: While (
@@ -4486,16 +4502,16 @@ impl<'a> LoweringContext<'a> {
44864502 arms. push ( self . arm ( pats, body_expr) ) ;
44874503 }
44884504
4489- // _ => [<else_opt>|() ]
4505+ // _ => [<else_opt>|{} ]
44904506 {
44914507 let wildcard_arm: Option < & Expr > = else_opt. as_ref ( ) . map ( |p| & * * p) ;
44924508 let wildcard_pattern = self . pat_wild ( e. span ) ;
44934509 let body = if let Some ( else_expr) = wildcard_arm {
4494- P ( self . lower_expr ( else_expr) )
4510+ self . lower_expr ( else_expr)
44954511 } else {
4496- P ( self . expr_tuple ( e. span , hir_vec ! [ ] ) )
4512+ self . expr_block_empty ( e. span )
44974513 } ;
4498- arms. push ( self . arm ( hir_vec ! [ wildcard_pattern] , body) ) ;
4514+ arms. push ( self . arm ( hir_vec ! [ wildcard_pattern] , P ( body) ) ) ;
44994515 }
45004516
45014517 let contains_else_clause = else_opt. is_some ( ) ;
@@ -4658,11 +4674,7 @@ impl<'a> LoweringContext<'a> {
46584674 ThinVec :: new ( ) ,
46594675 ) )
46604676 } ;
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) ) ;
46664678
46674679 let next_expr = P ( self . expr_ident ( head_sp, next_ident, next_pat_hid) ) ;
46684680
@@ -4685,11 +4697,7 @@ impl<'a> LoweringContext<'a> {
46854697
46864698 let body_block = self . with_loop_scope ( e. id , |this| this. lower_block ( body, false ) ) ;
46874699 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) ) ;
46934701
46944702 let loop_block = P ( self . block_all (
46954703 e. span ,
@@ -4869,12 +4877,7 @@ impl<'a> LoweringContext<'a> {
48694877 . into_iter( )
48704878 . map( |item_id| {
48714879 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) )
48784881 } )
48794882 . collect( ) ;
48804883 ids. push( {
@@ -5174,28 +5177,32 @@ impl<'a> LoweringContext<'a> {
51745177 }
51755178 }
51765179
5180+ fn stmt ( & mut self , span : Span , node : hir:: StmtKind ) -> hir:: Stmt {
5181+ hir:: Stmt { span, node, hir_id : self . next_id ( ) }
5182+ }
5183+
51775184 fn stmt_let_pat (
51785185 & mut self ,
5179- sp : Span ,
5180- ex : Option < P < hir:: Expr > > ,
5186+ span : Span ,
5187+ init : Option < P < hir:: Expr > > ,
51815188 pat : P < hir:: Pat > ,
51825189 source : hir:: LocalSource ,
51835190 ) -> hir:: Stmt {
51845191 let local = hir:: Local {
51855192 pat,
51865193 ty : None ,
5187- init : ex ,
5194+ init,
51885195 hir_id : self . next_id ( ) ,
5189- span : sp,
5190- attrs : ThinVec :: new ( ) ,
5196+ span,
51915197 source,
5198+ attrs : ThinVec :: new ( )
51925199 } ;
5200+ self . stmt ( span, hir:: StmtKind :: Local ( P ( local) ) )
5201+ }
51935202
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 ( ) )
51995206 }
52005207
52015208 fn block_expr ( & mut self , expr : P < hir:: Expr > ) -> hir:: Block {
@@ -5235,6 +5242,13 @@ impl<'a> LoweringContext<'a> {
52355242 )
52365243 }
52375244
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+
52385252 fn pat_ok ( & mut self , span : Span , pat : P < hir:: Pat > ) -> P < hir:: Pat > {
52395253 self . pat_std_enum ( span, & [ "result" , "Result" , "Ok" ] , hir_vec ! [ pat] )
52405254 }
@@ -5622,15 +5636,7 @@ impl<'a> LoweringContext<'a> {
56225636 & [ "task" , "Poll" , "Pending" ] ,
56235637 hir_vec ! [ ] ,
56245638 ) ;
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) ) ;
56345640 self . arm ( hir_vec ! [ pending_pat] , empty_block)
56355641 } ;
56365642
0 commit comments