Skip to content

Commit 25c3a4f

Browse files
committed
drop all temporary closure allocations
1 parent 35502fd commit 25c3a4f

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

src/eval_context.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ pub struct Frame<'tcx> {
8181
/// Temporary allocations introduced to save stackframes
8282
/// This is pure interpreter magic and has nothing to do with how rustc does it
8383
/// An example is calling an FnMut closure that has been converted to a FnOnce closure
84-
/// The memory will be freed when the stackframe finishes
85-
pub interpreter_temporaries: Vec<Pointer>,
84+
/// The value's destructor will be called and the memory freed when the stackframe finishes
85+
pub interpreter_temporaries: Vec<(Pointer, Ty<'tcx>)>,
8686

8787
////////////////////////////////////////////////////////////////////////////////
8888
// Current position within the function
@@ -273,7 +273,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
273273
substs: &'tcx Substs<'tcx>,
274274
return_lvalue: Lvalue<'tcx>,
275275
return_to_block: StackPopCleanup,
276-
temporaries: Vec<Pointer>,
276+
temporaries: Vec<(Pointer, Ty<'tcx>)>,
277277
) -> EvalResult<'tcx> {
278278
::log_settings::settings().indentation += 1;
279279

@@ -347,11 +347,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
347347
}
348348
}
349349
}
350-
// deallocate all temporary allocations
351-
for ptr in frame.interpreter_temporaries {
352-
trace!("deallocating temporary allocation");
353-
self.memory.dump_alloc(ptr.alloc_id);
354-
self.memory.deallocate(ptr)?;
350+
// drop and deallocate all temporary allocations
351+
for (ptr, ty) in frame.interpreter_temporaries {
352+
trace!("dropping temporary allocation");
353+
let mut drops = Vec::new();
354+
self.drop(Lvalue::from_ptr(ptr), ty, &mut drops)?;
355+
self.eval_drop_impls(drops, frame.span)?;
355356
}
356357
Ok(())
357358
}

src/traits.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
2323
def_id: DefId,
2424
substs: &'tcx Substs<'tcx>,
2525
args: &mut Vec<(Value, Ty<'tcx>)>,
26-
) -> EvalResult<'tcx, (DefId, &'tcx Substs<'tcx>, Vec<Pointer>)> {
26+
) -> EvalResult<'tcx, (DefId, &'tcx Substs<'tcx>, Vec<(Pointer, Ty<'tcx>)>)> {
2727
let trait_ref = ty::TraitRef::from_method(self.tcx, trait_id, substs);
2828
let trait_ref = self.tcx.normalize_associated_type(&ty::Binder(trait_ref));
2929

@@ -72,16 +72,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
7272
let ptr = self.alloc_ptr(args[0].1)?;
7373
let size = self.type_size(args[0].1)?.expect("closures are sized");
7474
self.memory.write_primval(ptr, primval, size)?;
75-
temporaries.push(ptr);
7675
ptr
7776
},
7877
Value::ByValPair(a, b) => {
7978
let ptr = self.alloc_ptr(args[0].1)?;
8079
self.write_pair_to_ptr(a, b, ptr, args[0].1)?;
81-
temporaries.push(ptr);
8280
ptr
8381
},
8482
};
83+
temporaries.push((ptr, args[0].1));
8584
args[0].0 = Value::ByVal(PrimVal::Ptr(ptr));
8685
args[0].1 = self.tcx.mk_mut_ptr(args[0].1);
8786
}

tests/run-pass/move_fn_closure.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
struct Foo<'a>(&'a mut bool);
2+
3+
impl<'a> Drop for Foo<'a> {
4+
fn drop(&mut self) {
5+
*self.0 = true;
6+
}
7+
}
8+
9+
fn f<T: FnOnce()>(t: T) {
10+
t()
11+
}
12+
13+
fn main() {
14+
let mut ran_drop = false;
15+
{
16+
let x = Foo(&mut ran_drop);
17+
// this closure never by val uses its captures
18+
// so it's basically a fn(&self)
19+
// the shim used to not drop the `x`
20+
let x = move || { let _ = x; };
21+
f(x);
22+
}
23+
assert!(ran_drop);
24+
}

0 commit comments

Comments
 (0)