about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-08-15 22:39:39 +0200
committerRalf Jung <post@ralfj.de>2018-08-22 09:06:28 +0200
commit09b15e9856c3ef77992cc30e772d29a896597041 (patch)
tree7ef6946875e4c43a7b483f5708563ba46e9f5a05
parente860ab2dabc281b8d882387fd62e78a6c072e6dc (diff)
downloadrust-09b15e9856c3ef77992cc30e772d29a896597041.tar.gz
rust-09b15e9856c3ef77992cc30e772d29a896597041.zip
fix dropping with vtables
-rw-r--r--src/librustc_mir/interpret/terminator/drop.rs17
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs3
2 files changed, 14 insertions, 6 deletions
diff --git a/src/librustc_mir/interpret/terminator/drop.rs b/src/librustc_mir/interpret/terminator/drop.rs
index 98ffacf6b4a..11fd7373284 100644
--- a/src/librustc_mir/interpret/terminator/drop.rs
+++ b/src/librustc_mir/interpret/terminator/drop.rs
@@ -30,24 +30,29 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
     ) -> EvalResult<'tcx> {
         trace!("drop: {:?},\n  {:?}, {:?}", arg, ty.sty, instance.def);
 
-        let instance = match ty.sty {
+        let (instance, arg) = match ty.sty {
             ty::TyDynamic(..) => {
-                if let Value::ScalarPair(_, vtable) = arg {
-                    self.read_drop_type_from_vtable(vtable.to_ptr()?)?
+                if let Value::ScalarPair(ptr, vtable) = arg {
+                    // Figure out the specific drop function to call, and just pass along
+                    // the thin part of the pointer.
+                    let instance = self.read_drop_type_from_vtable(vtable.to_ptr()?)?;
+                    trace!("Dropping via vtable: {:?}", instance.def);
+                    (instance, Value::Scalar(ptr))
                 } else {
                     bug!("expected fat ptr, got {:?}", arg);
                 }
             }
-            _ => instance,
+            _ => (instance, arg),
         };
 
         // the drop function expects a reference to the value
+        let fn_sig = self.tcx.fn_sig(instance.def_id()).skip_binder().clone();
         let arg = OpTy {
             op: Operand::Immediate(arg),
-            layout: self.layout_of(self.tcx.mk_mut_ptr(ty))?,
+            layout: self.layout_of(fn_sig.output())?,
         };
+        trace!("Dropped type: {:?}", fn_sig.output());
 
-        let fn_sig = self.tcx.fn_sig(instance.def_id()).skip_binder().clone();
         // This should always be (), but getting it from the sig seems
         // easier than creating a layout of ().
         let dest = PlaceTy::null(&self, self.layout_of(fn_sig.output())?);
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index c947a843463..e0980a4657e 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -257,6 +257,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
         sig: ty::FnSig<'tcx>,
     ) -> EvalResult<'tcx> {
         trace!("eval_fn_call: {:#?}", instance);
+        if let Some((place, _)) = destination {
+            assert_eq!(place.layout.ty, sig.output());
+        }
         match instance.def {
             ty::InstanceDef::Intrinsic(..) => {
                 let (ret, target) = match destination {