]> git.lizzy.rs Git - rust.git/commitdiff
drop all temporary closure allocations
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Tue, 14 Feb 2017 14:35:03 +0000 (15:35 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Fri, 24 Feb 2017 09:41:15 +0000 (10:41 +0100)
src/eval_context.rs
src/traits.rs
tests/run-pass/move_fn_closure.rs [new file with mode: 0644]

index 54aae64c5caaf9eee61da1441e5dafe699c9dc88..1bf71e149dc34914689f5caecf59866b17b69ab9 100644 (file)
@@ -81,8 +81,8 @@ pub struct Frame<'tcx> {
     /// Temporary allocations introduced to save stackframes
     /// This is pure interpreter magic and has nothing to do with how rustc does it
     /// An example is calling an FnMut closure that has been converted to a FnOnce closure
-    /// The memory will be freed when the stackframe finishes
-    pub interpreter_temporaries: Vec<Pointer>,
+    /// The value's destructor will be called and the memory freed when the stackframe finishes
+    pub interpreter_temporaries: Vec<(Pointer, Ty<'tcx>)>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -273,7 +273,7 @@ pub fn push_stack_frame(
         substs: &'tcx Substs<'tcx>,
         return_lvalue: Lvalue<'tcx>,
         return_to_block: StackPopCleanup,
-        temporaries: Vec<Pointer>,
+        temporaries: Vec<(Pointer, Ty<'tcx>)>,
     ) -> EvalResult<'tcx> {
         ::log_settings::settings().indentation += 1;
 
@@ -347,11 +347,12 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
                 }
             }
         }
-        // deallocate all temporary allocations
-        for ptr in frame.interpreter_temporaries {
-            trace!("deallocating temporary allocation");
-            self.memory.dump_alloc(ptr.alloc_id);
-            self.memory.deallocate(ptr)?;
+        // drop and deallocate all temporary allocations
+        for (ptr, ty) in frame.interpreter_temporaries {
+            trace!("dropping temporary allocation");
+            let mut drops = Vec::new();
+            self.drop(Lvalue::from_ptr(ptr), ty, &mut drops)?;
+            self.eval_drop_impls(drops, frame.span)?;
         }
         Ok(())
     }
index b892efbf569bb9e3190c13a94c9e0ab67f22419a..a46d6096dfc952095402abed38baccc54e0049e6 100644 (file)
@@ -23,7 +23,7 @@ pub(crate) fn trait_method(
         def_id: DefId,
         substs: &'tcx Substs<'tcx>,
         args: &mut Vec<(Value, Ty<'tcx>)>,
-    ) -> EvalResult<'tcx, (DefId, &'tcx Substs<'tcx>, Vec<Pointer>)> {
+    ) -> EvalResult<'tcx, (DefId, &'tcx Substs<'tcx>, Vec<(Pointer, Ty<'tcx>)>)> {
         let trait_ref = ty::TraitRef::from_method(self.tcx, trait_id, substs);
         let trait_ref = self.tcx.normalize_associated_type(&ty::Binder(trait_ref));
 
@@ -72,16 +72,15 @@ pub(crate) fn trait_method(
                                 let ptr = self.alloc_ptr(args[0].1)?;
                                 let size = self.type_size(args[0].1)?.expect("closures are sized");
                                 self.memory.write_primval(ptr, primval, size)?;
-                                temporaries.push(ptr);
                                 ptr
                             },
                             Value::ByValPair(a, b) => {
                                 let ptr = self.alloc_ptr(args[0].1)?;
                                 self.write_pair_to_ptr(a, b, ptr, args[0].1)?;
-                                temporaries.push(ptr);
                                 ptr
                             },
                         };
+                        temporaries.push((ptr, args[0].1));
                         args[0].0 = Value::ByVal(PrimVal::Ptr(ptr));
                         args[0].1 = self.tcx.mk_mut_ptr(args[0].1);
                     }
diff --git a/tests/run-pass/move_fn_closure.rs b/tests/run-pass/move_fn_closure.rs
new file mode 100644 (file)
index 0000000..e3e66c6
--- /dev/null
@@ -0,0 +1,24 @@
+struct Foo<'a>(&'a mut bool);
+
+impl<'a> Drop for Foo<'a> {
+    fn drop(&mut self) {
+        *self.0 = true;
+    }
+}
+
+fn f<T: FnOnce()>(t: T) {
+    t()
+}
+
+fn main() {
+    let mut ran_drop = false;
+    {
+        let x = Foo(&mut ran_drop);
+        // this closure never by val uses its captures
+        // so it's basically a fn(&self)
+        // the shim used to not drop the `x`
+        let x = move || { let _ = x; };
+        f(x);
+    }
+    assert!(ran_drop);
+}