fix a bug in drop code of structs with unsized fields

This commit is contained in:
Oliver Schneider 2017-02-14 12:48:46 +01:00
parent eeae478e74
commit 4730cdf825
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
2 changed files with 34 additions and 5 deletions

View file

@ -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)?;

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Send>> = wrapper;
}
assert_eq!(432, x)
}