@@ -58,52 +58,61 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
58
58
this. thir [ scrutinee] . span ,
59
59
) ,
60
60
ExprKind :: If { cond, then, else_opt, if_then_scope } => {
61
- let then_blk;
62
61
let then_span = this. thir [ then] . span ;
63
62
let then_source_info = this. source_info ( then_span) ;
64
63
let condition_scope = this. local_scope ( ) ;
65
64
66
- let mut else_blk = unpack ! (
67
- then_blk = this. in_scope(
68
- ( if_then_scope, then_source_info) ,
69
- LintLevel :: Inherited ,
70
- |this| {
71
- let source_info = if this. is_let( cond) {
72
- let variable_scope =
73
- this. new_source_scope( then_span, LintLevel :: Inherited , None ) ;
74
- this. source_scope = variable_scope;
75
- SourceInfo { span: then_span, scope: variable_scope }
76
- } else {
77
- this. source_info( then_span)
78
- } ;
79
- let ( then_block, else_block) =
80
- this. in_if_then_scope( condition_scope, then_span, |this| {
81
- let then_blk = unpack!( this. then_else_break(
82
- block,
83
- cond,
84
- Some ( condition_scope) , // Temp scope
85
- condition_scope,
86
- source_info,
87
- true , // Declare `let` bindings normally
88
- ) ) ;
89
-
90
- this. expr_into_dest( destination, then_blk, then)
91
- } ) ;
92
- then_block. and( else_block)
93
- } ,
94
- )
65
+ let then_and_else_blocks = this. in_scope (
66
+ ( if_then_scope, then_source_info) ,
67
+ LintLevel :: Inherited ,
68
+ |this| {
69
+ // FIXME: Does this need extra logic to handle let-chains?
70
+ let source_info = if this. is_let ( cond) {
71
+ let variable_scope =
72
+ this. new_source_scope ( then_span, LintLevel :: Inherited , None ) ;
73
+ this. source_scope = variable_scope;
74
+ SourceInfo { span : then_span, scope : variable_scope }
75
+ } else {
76
+ this. source_info ( then_span)
77
+ } ;
78
+
79
+ // Lower the condition, and have it branch into `then` and `else` blocks.
80
+ let ( then_block, else_block) =
81
+ this. in_if_then_scope ( condition_scope, then_span, |this| {
82
+ let then_blk = unpack ! ( this. then_else_break(
83
+ block,
84
+ cond,
85
+ Some ( condition_scope) , // Temp scope
86
+ condition_scope,
87
+ source_info,
88
+ true , // Declare `let` bindings normally
89
+ ) ) ;
90
+
91
+ // Lower the `then` arm into its block.
92
+ this. expr_into_dest ( destination, then_blk, then)
93
+ } ) ;
94
+
95
+ // Pack `(then_block, else_block)` into `BlockAnd<BasicBlock>`.
96
+ then_block. and ( else_block)
97
+ } ,
95
98
) ;
96
99
97
- else_blk = if let Some ( else_opt) = else_opt {
98
- unpack ! ( this. expr_into_dest( destination, else_blk, else_opt) )
100
+ // Unpack `BlockAnd<BasicBlock>` into `(then_blk, else_blk)`.
101
+ let ( then_blk, mut else_blk) ;
102
+ else_blk = unpack ! ( then_blk = then_and_else_blocks) ;
103
+
104
+ // If there is an `else` arm, lower it into `else_blk`.
105
+ if let Some ( else_expr) = else_opt {
106
+ unpack ! ( else_blk = this. expr_into_dest( destination, else_blk, else_expr) ) ;
99
107
} else {
100
- // Body of the `if` expression without an `else` clause must return `()`, thus
101
- // we implicitly generate an `else {}` if it is not specified .
108
+ // There is no `else` arm, so we know both arms have type `()`.
109
+ // Generate the implicit `else {}` by assigning unit .
102
110
let correct_si = this. source_info ( expr_span. shrink_to_hi ( ) ) ;
103
111
this. cfg . push_assign_unit ( else_blk, correct_si, destination, this. tcx ) ;
104
- else_blk
105
- } ;
112
+ }
106
113
114
+ // The `then` and `else` arms have been lowered into their respective
115
+ // blocks, so make both of them meet up in a new block.
107
116
let join_block = this. cfg . start_new_block ( ) ;
108
117
this. cfg . goto ( then_blk, source_info, join_block) ;
109
118
this. cfg . goto ( else_blk, source_info, join_block) ;
0 commit comments