@@ -158,42 +158,44 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
158
158
end_block. unit ( )
159
159
}
160
160
}
161
- ExprKind :: LogicalOp { .. } => {
161
+ ExprKind :: LogicalOp { op , lhs , rhs } => {
162
162
let condition_scope = this. local_scope ( ) ;
163
163
let source_info = this. source_info ( expr. span ) ;
164
+ // We first evaluate the left-hand side of the predicate ...
164
165
let ( then_block, else_block) =
165
166
this. in_if_then_scope ( condition_scope, expr. span , |this| {
166
167
this. then_else_break (
167
168
block,
168
- expr ,
169
+ & this . thir [ lhs ] ,
169
170
Some ( condition_scope) ,
170
171
condition_scope,
171
172
source_info,
172
173
)
173
174
} ) ;
175
+ let ( short_circuit, continuation, constant) = match op {
176
+ LogicalOp :: And => ( else_block, then_block, false ) ,
177
+ LogicalOp :: Or => ( then_block, else_block, true ) ,
178
+ } ;
179
+ // At this point, the control flow splits into a short-circuiting path
180
+ // and a continuation path.
181
+ // - If the operator is `&&`, passing `lhs` leads to continuation of evaluation on `rhs`;
182
+ // failing it leads to the short-circuting path which assigns `false` to the place.
183
+ // - If the operator is `||`, failing `lhs` leads to continuation of evaluation on `rhs`;
184
+ // passing it leads to the short-circuting path which assigns `true` to the place.
174
185
this. cfg . push_assign_constant (
175
- then_block,
176
- source_info,
177
- destination,
178
- Constant {
179
- span : expr. span ,
180
- user_ty : None ,
181
- literal : ConstantKind :: from_bool ( this. tcx , true ) ,
182
- } ,
183
- ) ;
184
- this. cfg . push_assign_constant (
185
- else_block,
186
+ short_circuit,
186
187
source_info,
187
188
destination,
188
189
Constant {
189
190
span : expr. span ,
190
191
user_ty : None ,
191
- literal : ConstantKind :: from_bool ( this. tcx , false ) ,
192
+ literal : ConstantKind :: from_bool ( this. tcx , constant ) ,
192
193
} ,
193
194
) ;
195
+ let rhs = unpack ! ( this. expr_into_dest( destination, continuation, & this. thir[ rhs] ) ) ;
194
196
let target = this. cfg . start_new_block ( ) ;
195
- this. cfg . goto ( then_block , source_info, target) ;
196
- this. cfg . goto ( else_block , source_info, target) ;
197
+ this. cfg . goto ( rhs , source_info, target) ;
198
+ this. cfg . goto ( short_circuit , source_info, target) ;
197
199
target. unit ( )
198
200
}
199
201
ExprKind :: Loop { body } => {
0 commit comments