Skip to content

refactor drop glue and fix Box<Box<Struct>> as Box<Trait> #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 10, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 9 additions & 16 deletions src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ pub enum Function<'tcx> {
Concrete(FunctionDefinition<'tcx>),
/// Glue required to call a regular function through a Fn(Mut|Once) trait object
FnDefAsTraitObject(FunctionDefinition<'tcx>),
/// Glue required to call the actual drop impl's `drop` method.
/// Drop glue takes the `self` by value, while `Drop::drop` take `&mut self`
DropGlue(FunctionDefinition<'tcx>),
/// A drop glue function only needs to know the real type, and then miri can extract the
/// actual type at runtime.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify "real type" vs "actual type"?

DropGlue(ty::Ty<'tcx>),
/// Glue required to treat the ptr part of a fat pointer
/// as a function pointer
FnPtrAsTraitObject(&'tcx ty::FnSig<'tcx>),
Expand All @@ -137,9 +137,9 @@ impl<'tcx> Function<'tcx> {
other => Err(EvalError::ExpectedConcreteFunction(other)),
}
}
pub fn expect_drop_glue(self) -> EvalResult<'tcx, FunctionDefinition<'tcx>> {
pub fn expect_drop_glue_real_ty(self) -> EvalResult<'tcx, ty::Ty<'tcx>> {
match self {
Function::DropGlue(fn_def) => Ok(fn_def),
Function::DropGlue(real_ty) => Ok(real_ty),
other => Err(EvalError::ExpectedDropGlue(other)),
}
}
Expand Down Expand Up @@ -234,15 +234,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
self.create_fn_alloc(Function::FnPtrAsTraitObject(fn_ty.sig.skip_binder()))
}

pub fn create_drop_glue(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>, fn_ty: &'tcx BareFnTy<'tcx>) -> Pointer {
self.create_fn_alloc(Function::DropGlue(FunctionDefinition {
def_id,
substs,
abi: fn_ty.abi,
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig: fn_ty.sig.skip_binder(),
}))
pub fn create_drop_glue(&mut self, ty: ty::Ty<'tcx>) -> Pointer {
self.create_fn_alloc(Function::DropGlue(ty))
}

pub fn create_fn_ptr(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>, fn_ty: &'tcx BareFnTy<'tcx>) -> Pointer {
Expand Down Expand Up @@ -495,8 +488,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
trace!("{} {}", msg, dump_fn_def(fn_def));
continue;
},
(None, Some(&Function::DropGlue(fn_def))) => {
trace!("{} drop glue for {}", msg, dump_fn_def(fn_def));
(None, Some(&Function::DropGlue(real_ty))) => {
trace!("{} drop glue for {}", msg, real_ty);
continue;
},
(None, Some(&Function::FnDefAsTraitObject(fn_def))) => {
Expand Down
10 changes: 2 additions & 8 deletions src/terminator/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use syntax::codemap::Span;
use error::{EvalError, EvalResult};
use eval_context::{EvalContext, monomorphize_field_ty, StackPopCleanup};
use lvalue::{Lvalue, LvalueExtra};
use memory::{Pointer, FunctionDefinition};
use memory::Pointer;
use value::PrimVal;
use value::Value;

Expand Down Expand Up @@ -166,13 +166,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
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) {
// FIXME: change the `DropGlue` variant of `Function` to only contain `real_ty`
let FunctionDefinition {substs, sig, ..} = self.memory.get_fn(drop_fn.alloc_id)?.expect_drop_glue()?;
// The real type is taken from the self argument in `fn drop(&mut self)`
let real_ty = match sig.inputs()[0].sty {
ty::TyRef(_, mt) => self.monomorphize(mt.ty, substs),
_ => bug!("first argument of Drop::drop must be &mut T"),
};
let real_ty = self.memory.get_fn(drop_fn.alloc_id)?.expect_drop_glue_real_ty()?;
self.drop(Lvalue::from_ptr(ptr), real_ty, drop)?;
} else {
// just a sanity check
Expand Down
7 changes: 6 additions & 1 deletion src/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
ty::TyFnDef(_, _, fn_ty) => self.tcx.erase_regions(&fn_ty),
_ => bug!("drop method is not a TyFnDef"),
};
let fn_ptr = self.memory.create_drop_glue(self.tcx, drop_def_id, substs, fn_ty);
// The real type is taken from the self argument in `fn drop(&mut self)`
let real_ty = match fn_ty.sig.skip_binder().inputs()[0].sty {
ty::TyRef(_, mt) => self.monomorphize(mt.ty, substs),
_ => bug!("first argument of Drop::drop must be &mut T"),
};
let fn_ptr = self.memory.create_drop_glue(real_ty);
self.memory.write_ptr(vtable, fn_ptr)?;
}
}
Expand Down