@@ -250,20 +250,32 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
250
250
ref l,
251
251
ref r,
252
252
) => {
253
- // For shortcircuiting operators, mark the RHS as a terminating
254
- // scope since it only executes conditionally.
253
+ // expr is a short circuiting operator (|| or &&). As its
254
+ // functionality can't be overridden by traits, it always
255
+ // processes bool sub-expressions. bools are Copy and thus we
256
+ // can drop any temporaries in evaluation (read) order
257
+ // (with the exception of potentially failing let expressions).
258
+ // We achieve this by enclosing the operands in a terminating
259
+ // scope, both the LHS and the RHS.
260
+
261
+ // We optimize this a little in the presence of chains.
262
+ // Chains like a && b && c get lowered to AND(AND(a, b), c).
263
+ // In here, b and c are RHS, while a is the only LHS operand in
264
+ // that chain. This holds true for longer chains as well: the
265
+ // leading operand is always the only LHS operand that is not a
266
+ // binop itself. Putting a binop like AND(a, b) into a
267
+ // terminating scope is not useful, thus we only put the LHS
268
+ // into a terminating scope if it is not a binop.
255
269
256
- // If the LHS is not another binop itself of the same kind as ours,
257
- // we also mark it as terminating, so that in && or || chains,
258
- // the temporaries are dropped in order instead of the very first
259
- // being dropped last. For the Let exception, see below.
260
270
let terminate_lhs = match l. kind {
261
271
hir:: ExprKind :: Let ( _) => false ,
262
272
hir:: ExprKind :: Binary ( source_map:: Spanned { node, .. } , ..)
263
273
if node == outer =>
264
274
{
265
275
false
266
276
}
277
+ // If the LHS is not another binop itself of the same kind as
278
+ // the current binop, mark it as terminating.
267
279
_ => true ,
268
280
} ;
269
281
if terminate_lhs {
0 commit comments