Skip to content

Commit 7faaf0e

Browse files
committed
Do not forget to drop the boxes on scope exits
Fixes #31463
1 parent 5147c1f commit 7faaf0e

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

src/librustc_mir/build/scope.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
236236
self.diverge_cleanup();
237237
let scope = self.scopes.pop().unwrap();
238238
assert_eq!(scope.extent, extent);
239-
build_scope_drops(block, &scope, &self.scopes[..], &mut self.cfg)
239+
build_scope_drops(&mut self.cfg, &scope, &self.scopes[..], block)
240240
}
241241

242242

@@ -254,8 +254,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
254254
self.hir.span_bug(span, &format!("extent {:?} does not enclose", extent))
255255
});
256256

257+
let tmp = self.get_unit_temp();
257258
for (idx, ref scope) in self.scopes.iter().enumerate().rev().take(scope_count) {
258-
unpack!(block = build_scope_drops(block, scope, &self.scopes[..idx], &mut self.cfg));
259+
unpack!(block = build_scope_drops(&mut self.cfg,
260+
scope,
261+
&self.scopes[..idx],
262+
block));
263+
if let Some(ref free_data) = scope.free {
264+
let next = self.cfg.start_new_block();
265+
let free = build_free(self.hir.tcx(), tmp.clone(), free_data, next);
266+
self.cfg.terminate(block, free);
267+
block = next;
268+
}
259269
}
260270
self.cfg.terminate(block, Terminator::Goto { target: target });
261271
}
@@ -508,10 +518,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
508518
}
509519

510520
/// Builds drops for pop_scope and exit_scope.
511-
fn build_scope_drops<'tcx>(mut block: BasicBlock,
521+
fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
512522
scope: &Scope<'tcx>,
513523
earlier_scopes: &[Scope<'tcx>],
514-
cfg: &mut CFG<'tcx>)
524+
mut block: BasicBlock)
515525
-> BlockAnd<()> {
516526
let mut iter = scope.drops.iter().rev().peekable();
517527
while let Some(drop_data) = iter.next() {
@@ -586,9 +596,10 @@ fn build_diverge_scope<'tcx>(tcx: &ty::ctxt<'tcx>,
586596
target = if let Some(cached_block) = free_data.cached_block {
587597
cached_block
588598
} else {
589-
let t = build_free(tcx, cfg, unit_temp, free_data, target);
590-
free_data.cached_block = Some(t);
591-
t
599+
let into = cfg.start_new_cleanup_block();
600+
cfg.terminate(into, build_free(tcx, unit_temp, free_data, target));
601+
free_data.cached_block = Some(into);
602+
into
592603
}
593604
};
594605

@@ -608,19 +619,16 @@ fn build_diverge_scope<'tcx>(tcx: &ty::ctxt<'tcx>,
608619
}
609620

610621
fn build_free<'tcx>(tcx: &ty::ctxt<'tcx>,
611-
cfg: &mut CFG<'tcx>,
612622
unit_temp: Lvalue<'tcx>,
613623
data: &FreeData<'tcx>,
614-
target: BasicBlock)
615-
-> BasicBlock {
624+
target: BasicBlock) -> Terminator<'tcx> {
616625
let free_func = tcx.lang_items.box_free_fn()
617626
.expect("box_free language item is missing");
618627
let substs = tcx.mk_substs(Substs::new(
619628
VecPerParamSpace::new(vec![], vec![], vec![data.item_ty]),
620629
VecPerParamSpace::new(vec![], vec![], vec![])
621630
));
622-
let block = cfg.start_new_cleanup_block();
623-
cfg.terminate(block, Terminator::Call {
631+
Terminator::Call {
624632
func: Operand::Constant(Constant {
625633
span: data.span,
626634
ty: tcx.lookup_item_type(free_func).ty.subst(tcx, substs),
@@ -633,6 +641,5 @@ fn build_free<'tcx>(tcx: &ty::ctxt<'tcx>,
633641
args: vec![Operand::Consume(data.value.clone())],
634642
destination: Some((unit_temp, target)),
635643
cleanup: None
636-
});
637-
block
644+
}
638645
}

0 commit comments

Comments
 (0)