diff options
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 46 |
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())); |
