add span/scope-id to terminator
This commit is contained in:
parent
3a16f57fbb
commit
9d00deee96
@ -230,6 +230,8 @@ pub struct BasicBlockData<'tcx> {
|
||||
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct Terminator<'tcx> {
|
||||
pub span: Span,
|
||||
pub scope: ScopeId,
|
||||
pub kind: TerminatorKind<'tcx>
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
StmtKind::Expr { scope, expr } => {
|
||||
unpack!(block = this.in_scope(scope, block, |this, _| {
|
||||
let expr = this.hir.mirror(expr);
|
||||
let expr_span = expr.span;
|
||||
let temp = this.temp(expr.ty.clone());
|
||||
unpack!(block = this.into(&temp, block, expr));
|
||||
unpack!(block = this.build_drop(block, temp));
|
||||
unpack!(block = this.build_drop(block, expr_span, temp));
|
||||
block.unit()
|
||||
}));
|
||||
}
|
||||
|
@ -83,11 +83,15 @@ impl<'tcx> CFG<'tcx> {
|
||||
|
||||
pub fn terminate(&mut self,
|
||||
block: BasicBlock,
|
||||
scope: ScopeId,
|
||||
span: Span,
|
||||
kind: TerminatorKind<'tcx>) {
|
||||
debug_assert!(self.block_data(block).terminator.is_none(),
|
||||
"terminate: block {:?} already has a terminator set", block);
|
||||
self.block_data_mut(block).terminator = Some(Terminator {
|
||||
kind: kind
|
||||
span: span,
|
||||
scope: scope,
|
||||
kind: kind,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
let (success, failure) = (this.cfg.start_new_block(), this.cfg.start_new_block());
|
||||
this.cfg.terminate(block,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::If {
|
||||
cond: Operand::Consume(lt),
|
||||
targets: (success, failure),
|
||||
|
@ -53,7 +53,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
let mut then_block = this.cfg.start_new_block();
|
||||
let mut else_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(block, TerminatorKind::If {
|
||||
this.cfg.terminate(block, scope_id, expr_span, TerminatorKind::If {
|
||||
cond: operand,
|
||||
targets: (then_block, else_block)
|
||||
});
|
||||
@ -70,8 +70,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
};
|
||||
|
||||
let join_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(then_block, TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(else_block, TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(then_block,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(else_block,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::Goto { target: join_block });
|
||||
|
||||
join_block.unit()
|
||||
}
|
||||
@ -97,10 +103,13 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
LogicalOp::And => (else_block, false_block),
|
||||
LogicalOp::Or => (true_block, else_block),
|
||||
};
|
||||
this.cfg.terminate(block, TerminatorKind::If { cond: lhs, targets: blocks });
|
||||
this.cfg.terminate(block,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::If { cond: lhs, targets: blocks });
|
||||
|
||||
let rhs = unpack!(else_block = this.as_operand(else_block, rhs));
|
||||
this.cfg.terminate(else_block, TerminatorKind::If {
|
||||
this.cfg.terminate(else_block, scope_id, expr_span, TerminatorKind::If {
|
||||
cond: rhs,
|
||||
targets: (true_block, false_block)
|
||||
});
|
||||
@ -121,8 +130,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
literal: this.hir.false_literal(),
|
||||
});
|
||||
|
||||
this.cfg.terminate(true_block, TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(false_block, TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(true_block,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::Goto { target: join_block });
|
||||
this.cfg.terminate(false_block,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::Goto { target: join_block });
|
||||
|
||||
join_block.unit()
|
||||
}
|
||||
@ -146,7 +161,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let exit_block = this.cfg.start_new_block();
|
||||
|
||||
// start the loop
|
||||
this.cfg.terminate(block, TerminatorKind::Goto { target: loop_block });
|
||||
this.cfg.terminate(block,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::Goto { target: loop_block });
|
||||
|
||||
let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
|
||||
// conduct the test, if necessary
|
||||
@ -159,6 +177,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
|
||||
body_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(loop_block_end,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::If {
|
||||
cond: cond,
|
||||
targets: (body_block, exit_block)
|
||||
@ -175,7 +195,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let tmp = this.get_unit_temp();
|
||||
// Execute the body, branching back to the test.
|
||||
let body_block_end = unpack!(this.into(&tmp, body_block, body));
|
||||
this.cfg.terminate(body_block_end, TerminatorKind::Goto { target: loop_block });
|
||||
this.cfg.terminate(body_block_end,
|
||||
scope_id,
|
||||
expr_span,
|
||||
TerminatorKind::Goto { target: loop_block });
|
||||
});
|
||||
// If the loop may reach its exit_block, we assign an empty tuple to the
|
||||
// destination to keep the MIR well-formed.
|
||||
@ -188,9 +211,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// Note: we evaluate assignments right-to-left. This
|
||||
// is better for borrowck interaction with overloaded
|
||||
// operators like x[j] = x[i].
|
||||
let lhs = this.hir.mirror(lhs);
|
||||
let lhs_span = lhs.span;
|
||||
let rhs = unpack!(block = this.as_operand(block, rhs));
|
||||
let lhs = unpack!(block = this.as_lvalue(block, lhs));
|
||||
unpack!(block = this.build_drop(block, lhs.clone()));
|
||||
unpack!(block = this.build_drop(block, lhs_span, lhs.clone()));
|
||||
this.cfg.push_assign(block, scope_id, expr_span, &lhs, Rvalue::Use(rhs));
|
||||
block.unit()
|
||||
}
|
||||
@ -254,7 +279,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
let success = this.cfg.start_new_block();
|
||||
let cleanup = this.diverge_cleanup();
|
||||
this.cfg.terminate(block, TerminatorKind::Call {
|
||||
this.cfg.terminate(block, scope_id, expr_span, TerminatorKind::Call {
|
||||
func: fun,
|
||||
args: args,
|
||||
cleanup: cleanup,
|
||||
|
@ -71,6 +71,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
})
|
||||
.map(|(arm_index, pattern, guard)| {
|
||||
Candidate {
|
||||
span: pattern.span,
|
||||
match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)],
|
||||
bindings: vec![],
|
||||
guard: guard,
|
||||
@ -87,7 +88,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// an empty vector to be returned here, but the algorithm is
|
||||
// not entirely precise
|
||||
if !otherwise.is_empty() {
|
||||
let join_block = self.join_otherwise_blocks(otherwise);
|
||||
let join_block = self.join_otherwise_blocks(span, otherwise);
|
||||
self.panic(join_block, "something about matches algorithm not being precise", span);
|
||||
}
|
||||
|
||||
@ -97,7 +98,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
for (arm_index, arm_body) in arm_bodies.into_iter().enumerate() {
|
||||
let mut arm_block = arm_blocks.blocks[arm_index];
|
||||
unpack!(arm_block = self.into(destination, arm_block, arm_body));
|
||||
self.cfg.terminate(arm_block, TerminatorKind::Goto { target: end_block });
|
||||
self.cfg.terminate(arm_block,
|
||||
var_scope_id,
|
||||
span,
|
||||
TerminatorKind::Goto { target: end_block });
|
||||
}
|
||||
|
||||
end_block.unit()
|
||||
@ -146,6 +150,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
// create a dummy candidate
|
||||
let mut candidate = Candidate {
|
||||
span: irrefutable_pat.span,
|
||||
match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
|
||||
bindings: vec![],
|
||||
guard: None,
|
||||
@ -206,6 +211,9 @@ struct ArmBlocks {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Candidate<'pat, 'tcx:'pat> {
|
||||
// span of the original pattern that gave rise to this candidate
|
||||
span: Span,
|
||||
|
||||
// all of these must be satisfied...
|
||||
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
|
||||
|
||||
@ -370,20 +378,25 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}
|
||||
|
||||
// Otherwise, let's process those remaining candidates.
|
||||
let join_block = self.join_otherwise_blocks(otherwise);
|
||||
let join_block = self.join_otherwise_blocks(span, otherwise);
|
||||
self.match_candidates(span, arm_blocks, untested_candidates, join_block)
|
||||
}
|
||||
|
||||
fn join_otherwise_blocks(&mut self,
|
||||
span: Span,
|
||||
otherwise: Vec<BasicBlock>)
|
||||
-> BasicBlock
|
||||
{
|
||||
let scope_id = self.innermost_scope_id();
|
||||
if otherwise.len() == 1 {
|
||||
otherwise[0]
|
||||
} else {
|
||||
let join_block = self.cfg.start_new_block();
|
||||
for block in otherwise {
|
||||
self.cfg.terminate(block, TerminatorKind::Goto { target: join_block });
|
||||
self.cfg.terminate(block,
|
||||
scope_id,
|
||||
span,
|
||||
TerminatorKind::Goto { target: join_block });
|
||||
}
|
||||
join_block
|
||||
}
|
||||
@ -550,16 +563,25 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
let arm_block = arm_blocks.blocks[candidate.arm_index];
|
||||
|
||||
let scope_id = self.innermost_scope_id();
|
||||
if let Some(guard) = candidate.guard {
|
||||
// the block to branch to if the guard fails; if there is no
|
||||
// guard, this block is simply unreachable
|
||||
let guard = self.hir.mirror(guard);
|
||||
let guard_span = guard.span;
|
||||
let cond = unpack!(block = self.as_operand(block, guard));
|
||||
let otherwise = self.cfg.start_new_block();
|
||||
self.cfg.terminate(block, TerminatorKind::If { cond: cond,
|
||||
targets: (arm_block, otherwise)});
|
||||
self.cfg.terminate(block,
|
||||
scope_id,
|
||||
guard_span,
|
||||
TerminatorKind::If { cond: cond,
|
||||
targets: (arm_block, otherwise)});
|
||||
Some(otherwise)
|
||||
} else {
|
||||
self.cfg.terminate(block, TerminatorKind::Goto { target: arm_block });
|
||||
self.cfg.terminate(block,
|
||||
scope_id,
|
||||
candidate.span,
|
||||
TerminatorKind::Goto { target: arm_block });
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let target_blocks: Vec<_> =
|
||||
(0..num_enum_variants).map(|_| self.cfg.start_new_block())
|
||||
.collect();
|
||||
self.cfg.terminate(block, TerminatorKind::Switch {
|
||||
self.cfg.terminate(block, scope_id, test.span, TerminatorKind::Switch {
|
||||
discr: lvalue.clone(),
|
||||
adt_def: adt_def,
|
||||
targets: target_blocks.clone()
|
||||
@ -168,12 +168,15 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
.map(|_| self.cfg.start_new_block())
|
||||
.chain(Some(otherwise))
|
||||
.collect();
|
||||
self.cfg.terminate(block, TerminatorKind::SwitchInt {
|
||||
discr: lvalue.clone(),
|
||||
switch_ty: switch_ty,
|
||||
values: options.clone(),
|
||||
targets: targets.clone(),
|
||||
});
|
||||
self.cfg.terminate(block,
|
||||
scope_id,
|
||||
test.span,
|
||||
TerminatorKind::SwitchInt {
|
||||
discr: lvalue.clone(),
|
||||
switch_ty: switch_ty,
|
||||
values: options.clone(),
|
||||
targets: targets.clone(),
|
||||
});
|
||||
targets
|
||||
}
|
||||
|
||||
@ -226,7 +229,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let eq_result = self.temp(bool_ty);
|
||||
let eq_block = self.cfg.start_new_block();
|
||||
let cleanup = self.diverge_cleanup();
|
||||
self.cfg.terminate(block, Terminator::Call {
|
||||
self.cfg.terminate(block, scope_id, test.span, TerminatorKind::Call {
|
||||
func: Operand::Constant(Constant {
|
||||
span: test.span,
|
||||
ty: mty,
|
||||
@ -239,7 +242,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
// check the result
|
||||
let block = self.cfg.start_new_block();
|
||||
self.cfg.terminate(eq_block, Terminator::If {
|
||||
self.cfg.terminate(eq_block, scope_id, test.span, TerminatorKind::If {
|
||||
cond: Operand::Consume(eq_result),
|
||||
targets: (block, fail),
|
||||
});
|
||||
@ -286,7 +289,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// branch based on result
|
||||
let target_blocks: Vec<_> = vec![self.cfg.start_new_block(),
|
||||
self.cfg.start_new_block()];
|
||||
self.cfg.terminate(block, TerminatorKind::If {
|
||||
self.cfg.terminate(block, scope_id, test.span, TerminatorKind::If {
|
||||
cond: Operand::Consume(result),
|
||||
targets: (target_blocks[0], target_blocks[1])
|
||||
});
|
||||
@ -313,7 +316,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
// branch based on result
|
||||
let target_block = self.cfg.start_new_block();
|
||||
self.cfg.terminate(block, TerminatorKind::If {
|
||||
self.cfg.terminate(block, scope_id, span, TerminatorKind::If {
|
||||
cond: Operand::Consume(result),
|
||||
targets: (target_block, fail_block)
|
||||
});
|
||||
@ -466,6 +469,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
.map(|(_, mp)| mp.clone())
|
||||
.collect();
|
||||
Candidate {
|
||||
span: candidate.span,
|
||||
match_pairs: other_match_pairs,
|
||||
bindings: candidate.bindings.clone(),
|
||||
guard: candidate.guard.clone(),
|
||||
@ -507,6 +511,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let all_match_pairs = consequent_match_pairs.chain(other_match_pairs).collect();
|
||||
|
||||
Candidate {
|
||||
span: candidate.span,
|
||||
match_pairs: all_match_pairs,
|
||||
bindings: candidate.bindings.clone(),
|
||||
guard: candidate.guard.clone(),
|
||||
|
@ -160,14 +160,17 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
|
||||
assert_eq!(builder.cfg.start_new_block(), END_BLOCK);
|
||||
|
||||
let mut block = START_BLOCK;
|
||||
let arg_decls = unpack!(block = builder.args_and_body(block,
|
||||
implicit_arguments,
|
||||
explicit_arguments,
|
||||
argument_extent,
|
||||
ast_block));
|
||||
let (arg_decls, arg_scope_id) =
|
||||
unpack!(block = builder.args_and_body(block,
|
||||
implicit_arguments,
|
||||
explicit_arguments,
|
||||
argument_extent,
|
||||
ast_block));
|
||||
|
||||
builder.cfg.terminate(block, TerminatorKind::Goto { target: END_BLOCK });
|
||||
builder.cfg.terminate(END_BLOCK, TerminatorKind::Return);
|
||||
builder.cfg.terminate(block, arg_scope_id, span,
|
||||
TerminatorKind::Goto { target: END_BLOCK });
|
||||
builder.cfg.terminate(END_BLOCK, arg_scope_id, span,
|
||||
TerminatorKind::Return);
|
||||
|
||||
MirPlusPlus {
|
||||
mir: Mir {
|
||||
@ -190,7 +193,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
|
||||
argument_extent: CodeExtent,
|
||||
ast_block: &'tcx hir::Block)
|
||||
-> BlockAnd<Vec<ArgDecl<'tcx>>>
|
||||
-> BlockAnd<(Vec<ArgDecl<'tcx>>, ScopeId)>
|
||||
{
|
||||
self.in_scope(argument_extent, block, |this, argument_scope_id| {
|
||||
// to start, translate the argument patterns and collect the argument types.
|
||||
@ -219,7 +222,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// start the first basic block and translate the body
|
||||
unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block));
|
||||
|
||||
block.and(arg_decls)
|
||||
block.and((arg_decls, argument_scope_id))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,7 @@ pub struct Scope<'tcx> {
|
||||
}
|
||||
|
||||
struct DropData<'tcx> {
|
||||
span: Span,
|
||||
value: Lvalue<'tcx>,
|
||||
// NB: per-drop “cache” is necessary for the build_scope_drops function below.
|
||||
/// The cached block for the cleanups-on-diverge path. This block contains code to run the
|
||||
@ -288,14 +289,19 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
if let Some(ref free_data) = scope.free {
|
||||
let next = self.cfg.start_new_block();
|
||||
let free = build_free(self.hir.tcx(), tmp.clone(), free_data, next);
|
||||
self.cfg.terminate(block, free);
|
||||
self.cfg.terminate(block, scope.id, span, free);
|
||||
block = next;
|
||||
}
|
||||
self.scope_auxiliary[scope.id.index()]
|
||||
.postdoms
|
||||
.push(self.cfg.current_location(block));
|
||||
}
|
||||
self.cfg.terminate(block, TerminatorKind::Goto { target: target });
|
||||
|
||||
let scope_id = self.innermost_scope_id();
|
||||
self.cfg.terminate(block,
|
||||
scope_id,
|
||||
span,
|
||||
TerminatorKind::Goto { target: target });
|
||||
}
|
||||
|
||||
// Finding scopes
|
||||
@ -351,6 +357,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// No need to invalidate any caches here. The just-scheduled drop will branch into
|
||||
// the drop that comes before it in the vector.
|
||||
scope.drops.push(DropData {
|
||||
span: span,
|
||||
value: lvalue.clone(),
|
||||
cached_block: None
|
||||
});
|
||||
@ -429,14 +436,22 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}
|
||||
|
||||
/// Utility function for *non*-scope code to build their own drops
|
||||
pub fn build_drop(&mut self, block: BasicBlock, value: Lvalue<'tcx>) -> BlockAnd<()> {
|
||||
pub fn build_drop(&mut self,
|
||||
block: BasicBlock,
|
||||
span: Span,
|
||||
value: Lvalue<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
let scope_id = self.innermost_scope_id();
|
||||
let next_target = self.cfg.start_new_block();
|
||||
let diverge_target = self.diverge_cleanup();
|
||||
self.cfg.terminate(block, TerminatorKind::Drop {
|
||||
value: value,
|
||||
target: next_target,
|
||||
unwind: diverge_target,
|
||||
});
|
||||
self.cfg.terminate(block,
|
||||
scope_id,
|
||||
span,
|
||||
TerminatorKind::Drop {
|
||||
value: value,
|
||||
target: next_target,
|
||||
unwind: diverge_target,
|
||||
});
|
||||
next_target.unit()
|
||||
}
|
||||
|
||||
@ -445,10 +460,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
// =========
|
||||
// FIXME: should be moved into their own module
|
||||
pub fn panic_bounds_check(&mut self,
|
||||
block: BasicBlock,
|
||||
index: Operand<'tcx>,
|
||||
len: Operand<'tcx>,
|
||||
span: Span) {
|
||||
block: BasicBlock,
|
||||
index: Operand<'tcx>,
|
||||
len: Operand<'tcx>,
|
||||
span: Span) {
|
||||
// fn(&(filename: &'static str, line: u32), index: usize, length: usize) -> !
|
||||
let region = ty::ReStatic; // FIXME(mir-borrowck): use a better region?
|
||||
let func = self.lang_function(lang_items::PanicBoundsCheckFnLangItem);
|
||||
@ -474,7 +489,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
self.cfg.push_assign(block, scope_id, span, &tuple_ref, // tuple_ref = &tuple;
|
||||
Rvalue::Ref(region, BorrowKind::Shared, tuple));
|
||||
let cleanup = self.diverge_cleanup();
|
||||
self.cfg.terminate(block, TerminatorKind::Call {
|
||||
self.cfg.terminate(block, scope_id, span, TerminatorKind::Call {
|
||||
func: Operand::Constant(func),
|
||||
args: vec![Operand::Consume(tuple_ref), index, len],
|
||||
destination: None,
|
||||
@ -516,7 +531,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
self.cfg.push_assign(block, scope_id, span, &tuple_ref, // tuple_ref = &tuple;
|
||||
Rvalue::Ref(region, BorrowKind::Shared, tuple));
|
||||
let cleanup = self.diverge_cleanup();
|
||||
self.cfg.terminate(block, TerminatorKind::Call {
|
||||
self.cfg.terminate(block, scope_id, span, TerminatorKind::Call {
|
||||
func: Operand::Constant(func),
|
||||
args: vec![Operand::Consume(tuple_ref)],
|
||||
cleanup: cleanup,
|
||||
@ -575,7 +590,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
|
||||
earlier_scopes.iter().rev().flat_map(|s| s.cached_block()).next()
|
||||
});
|
||||
let next = cfg.start_new_block();
|
||||
cfg.terminate(block, TerminatorKind::Drop {
|
||||
cfg.terminate(block, scope.id, drop_data.span, TerminatorKind::Drop {
|
||||
value: drop_data.value.clone(),
|
||||
target: next,
|
||||
unwind: on_diverge
|
||||
@ -599,12 +614,15 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
let mut last_drop_block = None;
|
||||
for drop_data in scope.drops.iter_mut().rev() {
|
||||
if let Some(cached_block) = drop_data.cached_block {
|
||||
if let Some((previous_block, previous_value)) = previous {
|
||||
cfg.terminate(previous_block, TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: cached_block,
|
||||
unwind: None
|
||||
});
|
||||
if let Some((previous_block, previous_span, previous_value)) = previous {
|
||||
cfg.terminate(previous_block,
|
||||
scope.id,
|
||||
previous_span,
|
||||
TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: cached_block,
|
||||
unwind: None
|
||||
});
|
||||
return last_drop_block.unwrap();
|
||||
} else {
|
||||
return cached_block;
|
||||
@ -612,23 +630,26 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
} else {
|
||||
let block = cfg.start_new_cleanup_block();
|
||||
drop_data.cached_block = Some(block);
|
||||
if let Some((previous_block, previous_value)) = previous {
|
||||
cfg.terminate(previous_block, TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: block,
|
||||
unwind: None
|
||||
});
|
||||
if let Some((previous_block, previous_span, previous_value)) = previous {
|
||||
cfg.terminate(previous_block,
|
||||
scope.id,
|
||||
previous_span,
|
||||
TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: block,
|
||||
unwind: None
|
||||
});
|
||||
} else {
|
||||
last_drop_block = Some(block);
|
||||
}
|
||||
previous = Some((block, drop_data.value.clone()));
|
||||
previous = Some((block, drop_data.span, drop_data.value.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the end target for this chain.
|
||||
let mut target = target.unwrap_or_else(||{
|
||||
let b = cfg.start_new_cleanup_block();
|
||||
cfg.terminate(b, TerminatorKind::Resume);
|
||||
cfg.terminate(b, scope.id, DUMMY_SP, TerminatorKind::Resume); // TODO
|
||||
b
|
||||
});
|
||||
|
||||
@ -638,19 +659,25 @@ fn build_diverge_scope<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
cached_block
|
||||
} else {
|
||||
let into = cfg.start_new_cleanup_block();
|
||||
cfg.terminate(into, build_free(tcx, unit_temp, free_data, target));
|
||||
cfg.terminate(into,
|
||||
scope.id,
|
||||
free_data.span,
|
||||
build_free(tcx, unit_temp, free_data, target));
|
||||
free_data.cached_block = Some(into);
|
||||
into
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((previous_block, previous_value)) = previous {
|
||||
if let Some((previous_block, previous_span, previous_value)) = previous {
|
||||
// Finally, branch into that just-built `target` from the `previous_block`.
|
||||
cfg.terminate(previous_block, TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: target,
|
||||
unwind: None
|
||||
});
|
||||
cfg.terminate(previous_block,
|
||||
scope.id,
|
||||
previous_span,
|
||||
TerminatorKind::Drop {
|
||||
value: previous_value,
|
||||
target: target,
|
||||
unwind: None
|
||||
});
|
||||
last_drop_block.unwrap()
|
||||
} else {
|
||||
// If `previous.is_none()`, there were no drops in this scope – we return the
|
||||
|
Loading…
Reference in New Issue
Block a user