about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDing Xiang Fei <dingxiangfei2009@protonmail.ch>2023-08-02 05:34:55 +0800
committerDing Xiang Fei <dingxiangfei2009@protonmail.ch>2023-08-30 17:24:11 +0800
commit39cf0b5dd585cc5689ab02c9ea0e509c2fcf698b (patch)
tree8d8ad839c0317c07f88cf33ff053220bd18b2107
parentd9ed11872fc4060dbb5d8260dee1e4d20870e5cc (diff)
downloadrust-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.rs34
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 } => {