use if only on lhs of binary logical exprs

This commit is contained in:
Ding Xiang Fei 2023-08-02 05:34:55 +08:00
parent d9ed11872f
commit 39cf0b5dd5
No known key found for this signature in database
GPG Key ID: 3CD748647EEF6359

View File

@ -158,42 +158,44 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
end_block.unit() end_block.unit()
} }
} }
ExprKind::LogicalOp { .. } => { ExprKind::LogicalOp { op, lhs, rhs } => {
let condition_scope = this.local_scope(); let condition_scope = this.local_scope();
let source_info = this.source_info(expr.span); let source_info = this.source_info(expr.span);
// We first evaluate the left-hand side of the predicate ...
let (then_block, else_block) = let (then_block, else_block) =
this.in_if_then_scope(condition_scope, expr.span, |this| { this.in_if_then_scope(condition_scope, expr.span, |this| {
this.then_else_break( this.then_else_break(
block, block,
expr, &this.thir[lhs],
Some(condition_scope), Some(condition_scope),
condition_scope, condition_scope,
source_info, source_info,
) )
}); });
let (short_circuit, continuation, constant) = match op {
LogicalOp::And => (else_block, then_block, false),
LogicalOp::Or => (then_block, else_block, true),
};
// At this point, the control flow splits into a short-circuiting path
// and a continuation path.
// - If the operator is `&&`, passing `lhs` leads to continuation of evaluation on `rhs`;
// failing it leads to the short-circuting path which assigns `false` to the place.
// - If the operator is `||`, failing `lhs` leads to continuation of evaluation on `rhs`;
// passing it leads to the short-circuting path which assigns `true` to the place.
this.cfg.push_assign_constant( this.cfg.push_assign_constant(
then_block, short_circuit,
source_info, source_info,
destination, destination,
Constant { Constant {
span: expr.span, span: expr.span,
user_ty: None, user_ty: None,
literal: ConstantKind::from_bool(this.tcx, true), literal: ConstantKind::from_bool(this.tcx, constant),
},
);
this.cfg.push_assign_constant(
else_block,
source_info,
destination,
Constant {
span: expr.span,
user_ty: None,
literal: ConstantKind::from_bool(this.tcx, false),
}, },
); );
let rhs = unpack!(this.expr_into_dest(destination, continuation, &this.thir[rhs]));
let target = this.cfg.start_new_block(); let target = this.cfg.start_new_block();
this.cfg.goto(then_block, source_info, target); this.cfg.goto(rhs, source_info, target);
this.cfg.goto(else_block, source_info, target); this.cfg.goto(short_circuit, source_info, target);
target.unit() target.unit()
} }
ExprKind::Loop { body } => { ExprKind::Loop { body } => {