diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2021-02-25 22:37:22 +0000 |
|---|---|---|
| committer | Caio <c410.f3r@gmail.com> | 2021-08-15 16:05:25 -0300 |
| commit | 2d9f2eae84dc3988c5463fdd1b124a9b695447d7 (patch) | |
| tree | 373c546d14e21ad7e4315d367c145f7ae00739b2 | |
| parent | c0490a2dbbb94f8244fb6a15ca5d33dc3fcd268a (diff) | |
| download | rust-2d9f2eae84dc3988c5463fdd1b124a9b695447d7.tar.gz rust-2d9f2eae84dc3988c5463fdd1b124a9b695447d7.zip | |
Use correct drop scopes for if expressions
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/matches/mod.rs | 41 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/region.rs | 24 |
3 files changed, 75 insertions, 7 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index bacf5662bc0..3bf7c7c37a4 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -443,9 +443,20 @@ impl<'hir> LoweringContext<'_, 'hir> { else_opt: Option<&Expr>, ) -> hir::ExprKind<'hir> { let cond = self.lower_expr(cond); - let then = self.arena.alloc(self.lower_block_expr(then)); - let els = else_opt.map(|els| self.lower_expr(els)); - hir::ExprKind::If(cond, then, els) + let wrapped_cond = match cond.kind { + hir::ExprKind::Let(..) => cond, + _ => self.expr_drop_temps(cond.span, cond, AttrVec::new()), + }; + let then_expr = self.lower_block_expr(then); + if let Some(rslt) = else_opt { + hir::ExprKind::If( + wrapped_cond, + self.arena.alloc(then_expr), + Some(self.lower_expr(rslt)), + ) + } else { + hir::ExprKind::If(wrapped_cond, self.arena.alloc(then_expr), None) + } } fn lower_expr_if_let( diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 8164529dd1f..9ca4425a1b5 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -35,6 +35,47 @@ use std::convert::TryFrom; use std::mem; impl<'a, 'tcx> Builder<'a, 'tcx> { + pub(crate) fn then_else_blocks( + &mut self, + mut block: BasicBlock, + expr: ExprRef<'tcx>, + source_info: SourceInfo, + ) -> (BasicBlock, BasicBlock) { + let this = self; + let expr = this.hir.mirror(expr); + let expr_span = expr.span; + + match expr.kind { + ExprKind::Scope { region_scope, lint_level, value } => { + let region_scope = (region_scope, source_info); + let then_block; + let else_block = unpack!( + then_block = this.in_scope(region_scope, lint_level, |this| { + let (then_block, else_block) = + this.then_else_blocks(block, value, source_info); + then_block.and(else_block) + }) + ); + (then_block, else_block) + } + ExprKind::Let { expr, pat } => { + // TODO: Use correct span. + this.lower_let(block, &expr, &pat, expr_span) + } + _ => { + let local_scope = Some(this.local_scope()); + let place = + unpack!(block = this.as_temp(block, local_scope, expr, Mutability::Mut)); + let operand = Operand::Move(Place::from(place)); + let then_block = this.cfg.start_new_block(); + let else_block = this.cfg.start_new_block(); + let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block); + this.cfg.terminate(block, source_info, term); + (then_block, else_block) + } + } + } + /// Generates MIR for a `match` expression. /// /// The MIR that we generate for a match looks like this. diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index c133f1a0417..7403e51c734 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -233,14 +233,12 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h terminating(r.hir_id.local_id); } - hir::ExprKind::If(ref expr, ref then, Some(ref otherwise)) => { - terminating(expr.hir_id.local_id); + hir::ExprKind::If(_, ref then, Some(ref otherwise)) => { terminating(then.hir_id.local_id); terminating(otherwise.hir_id.local_id); } - hir::ExprKind::If(ref expr, ref then, None) => { - terminating(expr.hir_id.local_id); + hir::ExprKind::If(_, ref then, None) => { terminating(then.hir_id.local_id); } @@ -392,6 +390,24 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h } } + hir::ExprKind::If(ref cond, ref then, Some(ref otherwise)) => { + // FIXME(matthewjasper): ideally the scope we use here would only + // contain the condition and then expression. This works, but + // can result in some extra drop flags. + visitor.cx.var_parent = visitor.cx.parent; + visitor.visit_expr(cond); + visitor.cx.var_parent = prev_cx.var_parent; + visitor.visit_expr(then); + visitor.visit_expr(otherwise); + } + + hir::ExprKind::If(ref cond, ref then, None) => { + visitor.cx.var_parent = visitor.cx.parent; + visitor.visit_expr(cond); + visitor.cx.var_parent = prev_cx.var_parent; + visitor.visit_expr(then); + } + _ => intravisit::walk_expr(visitor, expr), } |
