diff options
| author | Ding Xiang Fei <dingxiangfei2009@protonmail.ch> | 2023-08-02 05:34:55 +0800 |
|---|---|---|
| committer | Ding Xiang Fei <dingxiangfei2009@protonmail.ch> | 2023-08-30 17:24:11 +0800 |
| commit | 39cf0b5dd585cc5689ab02c9ea0e509c2fcf698b (patch) | |
| tree | 8d8ad839c0317c07f88cf33ff053220bd18b2107 | |
| parent | d9ed11872fc4060dbb5d8260dee1e4d20870e5cc (diff) | |
| download | rust-39cf0b5dd585cc5689ab02c9ea0e509c2fcf698b.tar.gz rust-39cf0b5dd585cc5689ab02c9ea0e509c2fcf698b.zip | |
use if only on lhs of binary logical exprs
| -rw-r--r-- | compiler/rustc_mir_build/src/build/expr/into.rs | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index aecab5635aa..1e0a47ead8c 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -158,42 +158,44 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { end_block.unit() } } - ExprKind::LogicalOp { .. } => { + ExprKind::LogicalOp { op, lhs, rhs } => { let condition_scope = this.local_scope(); let source_info = this.source_info(expr.span); + // We first evaluate the left-hand side of the predicate ... let (then_block, else_block) = this.in_if_then_scope(condition_scope, expr.span, |this| { this.then_else_break( block, - expr, + &this.thir[lhs], Some(condition_scope), condition_scope, 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( - then_block, - source_info, - destination, - Constant { - span: expr.span, - user_ty: None, - literal: ConstantKind::from_bool(this.tcx, true), - }, - ); - this.cfg.push_assign_constant( - else_block, + short_circuit, source_info, destination, Constant { span: expr.span, user_ty: None, - literal: ConstantKind::from_bool(this.tcx, false), + literal: ConstantKind::from_bool(this.tcx, constant), }, ); + let rhs = unpack!(this.expr_into_dest(destination, continuation, &this.thir[rhs])); let target = this.cfg.start_new_block(); - this.cfg.goto(then_block, source_info, target); - this.cfg.goto(else_block, source_info, target); + this.cfg.goto(rhs, source_info, target); + this.cfg.goto(short_circuit, source_info, target); target.unit() } ExprKind::Loop { body } => { |
