Use correct drop scopes for if expressions
This commit is contained in:
parent
c0490a2dbb
commit
2d9f2eae84
3 changed files with 75 additions and 7 deletions
|
@ -443,9 +443,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
else_opt: Option<&Expr>,
|
else_opt: Option<&Expr>,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::ExprKind<'hir> {
|
||||||
let cond = self.lower_expr(cond);
|
let cond = self.lower_expr(cond);
|
||||||
let then = self.arena.alloc(self.lower_block_expr(then));
|
let wrapped_cond = match cond.kind {
|
||||||
let els = else_opt.map(|els| self.lower_expr(els));
|
hir::ExprKind::Let(..) => cond,
|
||||||
hir::ExprKind::If(cond, then, els)
|
_ => 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(
|
fn lower_expr_if_let(
|
||||||
|
|
|
@ -35,6 +35,47 @@ use std::convert::TryFrom;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
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.
|
/// Generates MIR for a `match` expression.
|
||||||
///
|
///
|
||||||
/// The MIR that we generate for a match looks like this.
|
/// The MIR that we generate for a match looks like this.
|
||||||
|
|
|
@ -233,14 +233,12 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
|
||||||
terminating(r.hir_id.local_id);
|
terminating(r.hir_id.local_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::If(ref expr, ref then, Some(ref otherwise)) => {
|
hir::ExprKind::If(_, ref then, Some(ref otherwise)) => {
|
||||||
terminating(expr.hir_id.local_id);
|
|
||||||
terminating(then.hir_id.local_id);
|
terminating(then.hir_id.local_id);
|
||||||
terminating(otherwise.hir_id.local_id);
|
terminating(otherwise.hir_id.local_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::If(ref expr, ref then, None) => {
|
hir::ExprKind::If(_, ref then, None) => {
|
||||||
terminating(expr.hir_id.local_id);
|
|
||||||
terminating(then.hir_id.local_id);
|
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),
|
_ => intravisit::walk_expr(visitor, expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue