From 4730cdf8250192d1fb268dd027b9cb40fa6fe370 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 14 Feb 2017 12:48:46 +0100 Subject: [PATCH] fix a bug in drop code of structs with unsized fields --- src/terminator/drop.rs | 13 ++++++++----- tests/run-pass/issue-26709.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 tests/run-pass/issue-26709.rs diff --git a/src/terminator/drop.rs b/src/terminator/drop.rs index c8875398918f..71f3d4673660 100644 --- a/src/terminator/drop.rs +++ b/src/terminator/drop.rs @@ -94,10 +94,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyAdt(adt_def, substs) => { // FIXME: some structs are represented as ByValPair let mut lval = self.force_allocation(lval)?; - let adt_ptr = match lval { - Lvalue::Ptr { ptr, .. } => ptr, - _ => bug!("force allocation can only yield Lvalue::Ptr"), - }; + let (adt_ptr, extra) = lval.to_ptr_and_extra(); // run drop impl before the fields' drop impls if let Some(drop_def_id) = adt_def.destructor() { @@ -109,7 +106,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { traits::VtableImpl(data) => data, _ => bug!("dtor for {:?} is not an impl???", ty) }; - drop.push((drop_def_id, Value::ByVal(PrimVal::Ptr(adt_ptr)), vtable.substs)); + let val = match extra { + LvalueExtra::None => Value::ByVal(PrimVal::Ptr(adt_ptr)), + LvalueExtra::DowncastVariant(_) => bug!("downcast variant in drop"), + LvalueExtra::Length(n) => Value::ByValPair(PrimVal::Ptr(adt_ptr), PrimVal::from_u128(n as u128)), + LvalueExtra::Vtable(vtable) => Value::ByValPair(PrimVal::Ptr(adt_ptr), PrimVal::Ptr(vtable)), + }; + drop.push((drop_def_id, val, vtable.substs)); } let layout = self.type_layout(ty)?; diff --git a/tests/run-pass/issue-26709.rs b/tests/run-pass/issue-26709.rs new file mode 100644 index 000000000000..62626d75865c --- /dev/null +++ b/tests/run-pass/issue-26709.rs @@ -0,0 +1,26 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Wrapper<'a, T: ?Sized>(&'a mut i32, T); + +impl<'a, T: ?Sized> Drop for Wrapper<'a, T> { + fn drop(&mut self) { + *self.0 = 432; + } +} + +fn main() { + let mut x = 0; + { + let wrapper = Box::new(Wrapper(&mut x, 123)); + let _: Box> = wrapper; + } + assert_eq!(432, x) +}