diff --git a/src/terminator/drop.rs b/src/terminator/drop.rs index dd199a4266c1..f334e9e7685d 100644 --- a/src/terminator/drop.rs +++ b/src/terminator/drop.rs @@ -178,14 +178,8 @@ pub fn drop( Lvalue::Ptr { ptr, extra: LvalueExtra::Vtable(vtable) } => (ptr, vtable), _ => bug!("expected an lvalue with a vtable"), }; - let drop_fn = self.memory.read_ptr(vtable)?; - // some values don't need to call a drop impl, so the value is null - if drop_fn != Pointer::from_int(0) { - let real_ty = self.memory.get_fn(drop_fn.alloc_id)?.expect_drop_glue_real_ty()?; + if let Some(real_ty) = self.read_drop_type_from_vtable(vtable)? { self.drop(Lvalue::from_ptr(ptr), real_ty, drop)?; - } else { - // just a sanity check - assert_eq!(drop_fn.offset, 0); } } diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 0443206e80db..ab8539be3154 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -418,7 +418,6 @@ pub fn size_and_align_of_dst( ty: ty::Ty<'tcx>, value: Value, ) -> EvalResult<'tcx, (u64, u64)> { - let pointer_size = self.memory.pointer_size(); if let Some(size) = self.type_size(ty)? { Ok((size as u64, self.type_align(ty)? as u64)) } else { @@ -481,9 +480,7 @@ pub fn size_and_align_of_dst( ty::TyDynamic(..) => { let (_, vtable) = value.expect_ptr_vtable_pair(&self.memory)?; // the second entry in the vtable is the dynamic size of the object. - let size = self.memory.read_usize(vtable.offset(pointer_size))?; - let align = self.memory.read_usize(vtable.offset(pointer_size * 2))?; - Ok((size, align)) + self.read_size_and_align_from_vtable(vtable) } ty::TySlice(_) | ty::TyStr => { diff --git a/src/traits.rs b/src/traits.rs index a46d6096dfc9..733095322d00 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -285,6 +285,27 @@ pub fn get_vtable(&mut self, trait_ref: ty::PolyTraitRef<'tcx>) -> EvalResult<'t Ok(vtable) } + pub fn read_drop_type_from_vtable(&self, vtable: Pointer) -> EvalResult<'tcx, Option>> { + let drop_fn = self.memory.read_ptr(vtable)?; + + // just a sanity check + assert_eq!(drop_fn.offset, 0); + + // some values don't need to call a drop impl, so the value is null + if drop_fn == Pointer::from_int(0) { + Ok(None) + } else { + self.memory.get_fn(drop_fn.alloc_id)?.expect_drop_glue_real_ty().map(Some) + } + } + + pub fn read_size_and_align_from_vtable(&self, vtable: Pointer) -> EvalResult<'tcx, (u64, u64)> { + let pointer_size = self.memory.pointer_size(); + let size = self.memory.read_usize(vtable.offset(pointer_size))?; + let align = self.memory.read_usize(vtable.offset(pointer_size * 2))?; + Ok((size, align)) + } + fn get_vtable_methods(&mut self, impl_id: DefId, substs: &'tcx Substs<'tcx>) -> Vec>> { debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs);