about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs46
1 files changed, 24 insertions, 22 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 104010f8d43..ec9c3935020 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -387,23 +387,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
         then: &Block,
         else_opt: Option<&Expr>,
     ) -> hir::ExprKind<'hir> {
-        let lowered_cond = self.lower_expr(cond);
-        let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
+        let lowered_cond = self.lower_cond(cond);
         let then_expr = self.lower_block_expr(then);
         if let Some(rslt) = else_opt {
-            hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
+            hir::ExprKind::If(
+                lowered_cond,
+                self.arena.alloc(then_expr),
+                Some(self.lower_expr(rslt)),
+            )
         } else {
-            hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), None)
+            hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
         }
     }
 
-    // Wraps a condition (i.e. `cond` in `if cond` or `while cond`) in a terminating scope
+    // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
     // so that temporaries created in the condition don't live beyond it.
-    fn wrap_cond_in_drop_scope(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
-        fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
-            match expr.kind {
-                hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
-                hir::ExprKind::Let(..) => true,
+    fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
+        fn has_let_expr(expr: &Expr) -> bool {
+            match &expr.kind {
+                ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
+                ExprKind::Let(..) => true,
                 _ => false,
             }
         }
@@ -415,14 +418,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // In order to mantain the drop behavior for the non `let` parts of the condition,
         // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
         // gets transformed into `if { let _t = foo; _t } && let pat = val`
-        match cond.kind {
-            hir::ExprKind::Binary(
-                op @ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
-                lhs,
-                rhs,
-            ) if has_let_expr(cond) => {
-                let lhs = self.wrap_cond_in_drop_scope(lhs);
-                let rhs = self.wrap_cond_in_drop_scope(rhs);
+        match &cond.kind {
+            ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
+                if has_let_expr(cond) =>
+            {
+                let op = self.lower_binop(*op);
+                let lhs = self.lower_cond(lhs);
+                let rhs = self.lower_cond(rhs);
 
                 self.arena.alloc(self.expr(
                     cond.span,
@@ -430,8 +432,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     AttrVec::new(),
                 ))
             }
-            hir::ExprKind::Let(_) => cond,
+            ExprKind::Let(..) => self.lower_expr(cond),
             _ => {
+                let cond = self.lower_expr(cond);
                 let reason = DesugaringKind::CondTemporary;
                 let span_block = self.mark_span_with_reason(reason, cond.span, None);
                 self.expr_drop_temps(span_block, cond, AttrVec::new())
@@ -462,14 +465,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         body: &Block,
         opt_label: Option<Label>,
     ) -> hir::ExprKind<'hir> {
-        let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
-        let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
+        let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
         let then = self.lower_block_expr(body);
         let expr_break = self.expr_break(span, AttrVec::new());
         let stmt_break = self.stmt_expr(span, expr_break);
         let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
         let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
-        let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
+        let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
         let if_expr = self.expr(span, if_kind, AttrVec::new());
         let block = self.block_expr(self.arena.alloc(if_expr));
         let span = self.lower_span(span.with_hi(cond.span.hi()));