@@ -250,20 +250,32 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
250250 ref l,
251251 ref r,
252252 ) => {
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.
255269
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.
260270 let terminate_lhs = match l. kind {
261271 hir:: ExprKind :: Let ( _) => false ,
262272 hir:: ExprKind :: Binary ( source_map:: Spanned { node, .. } , ..)
263273 if node == outer =>
264274 {
265275 false
266276 }
277+ // If the LHS is not another binop itself of the same kind as
278+ // the current binop, mark it as terminating.
267279 _ => true ,
268280 } ;
269281 if terminate_lhs {
0 commit comments