Skip to content

Commit

Permalink
Support an alternative form for box_free
Browse files Browse the repository at this point in the history
box_free currently takes a pointer. With the prospect of the Box type
definition changing in the future to include an allocator, box_free will
also need to be aware of this. In order to prepare for that future, we
allow box_free to take a form where its argument are the fields of the
Box.

e.g. if Box is defined as `Box(A, B, C)`, then box_free signature
becomes `box_free(a: A, b: B, c: C)`.

We however still allow the current form (taking a pointer), so that the
same compiler can handle both forms, which helps with bootstrap.
  • Loading branch information
glandium committed Apr 20, 2018
1 parent dfa6111 commit 6614fa0
Showing 1 changed file with 44 additions and 24 deletions.
68 changes: 44 additions & 24 deletions src/librustc_mir/util/elaborate_drops.rs
Expand Up @@ -337,18 +337,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
self.drop_ladder(fields, succ, unwind).0
}

fn open_drop_for_box<'a>(&mut self, ty: Ty<'tcx>) -> BasicBlock
fn open_drop_for_box<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
-> BasicBlock
{
debug!("open_drop_for_box({:?}, {:?})", self, ty);
debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs);

let interior = self.place.clone().deref();
let interior_path = self.elaborator.deref_subpath(self.path);

let succ = self.succ; // FIXME(#43234)
let unwind = self.unwind;
let succ = self.box_free_block(ty, succ, unwind);
let succ = self.box_free_block(adt, substs, succ, unwind);
let unwind_succ = self.unwind.map(|unwind| {
self.box_free_block(ty, unwind, Unwind::InCleanup)
self.box_free_block(adt, substs, unwind, Unwind::InCleanup)
});

self.drop_subpath(&interior, interior_path, succ, unwind_succ)
Expand Down Expand Up @@ -791,11 +792,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
ty::TyTuple(tys) => {
self.open_drop_for_tuple(tys)
}
ty::TyAdt(def, _) if def.is_box() => {
self.open_drop_for_box(ty.boxed_ty())
}
ty::TyAdt(def, substs) => {
self.open_drop_for_adt(def, substs)
if def.is_box() {
self.open_drop_for_box(def, substs)
} else {
self.open_drop_for_adt(def, substs)
}
}
ty::TyDynamic(..) => {
let unwind = self.unwind; // FIXME(#43234)
Expand Down Expand Up @@ -858,34 +860,40 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>

fn box_free_block<'a>(
&mut self,
ty: Ty<'tcx>,
adt: &'tcx ty::AdtDef,
substs: &'tcx Substs<'tcx>,
target: BasicBlock,
unwind: Unwind,
) -> BasicBlock {
let block = self.unelaborated_free_block(ty, target, unwind);
let block = self.unelaborated_free_block(adt, substs, target, unwind);
self.drop_flag_test_block(block, target, unwind)
}

fn unelaborated_free_block<'a>(
&mut self,
ty: Ty<'tcx>,
adt: &'tcx ty::AdtDef,
substs: &'tcx Substs<'tcx>,
target: BasicBlock,
unwind: Unwind
) -> BasicBlock {
let tcx = self.tcx();
let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
ty: ty,
mutbl: hir::Mutability::MutMutable
});
let ptr_ty = tcx.mk_mut_ptr(ty);
let ref_tmp = Place::Local(self.new_temp(ref_ty));
let ptr_tmp = Place::Local(self.new_temp(ptr_ty));

let free_block = BasicBlockData {
statements: vec![
let free_sig = tcx.fn_sig(free_func).skip_binder().clone();
let free_inputs = free_sig.inputs();
// If the box_free function takes a *mut T, transform the Box into
// such a pointer before calling box_free. Otherwise, pass it all
// the fields in the Box as individual arguments.
let (stmts, args) = if free_inputs.len() == 1 && free_inputs[0].is_mutable_pointer() {
let ty = substs.type_at(0);
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
ty: ty,
mutbl: hir::Mutability::MutMutable
});
let ptr_ty = tcx.mk_mut_ptr(ty);
let ref_tmp = Place::Local(self.new_temp(ref_ty));
let ptr_tmp = Place::Local(self.new_temp(ptr_ty));
let stmts = vec![
self.assign(&ref_tmp, Rvalue::Ref(
tcx.types.re_erased,
BorrowKind::Mut { allow_two_phase_borrow: false },
Expand All @@ -896,11 +904,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
Operand::Move(ref_tmp),
ptr_ty,
)),
],
];
(stmts, vec![Operand::Move(ptr_tmp)])
} else {
let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
let field = Field::new(i);
let field_ty = f.ty(self.tcx(), substs);
Operand::Move(self.place.clone().field(field, field_ty))
}).collect();
(vec![], args)
};

let free_block = BasicBlockData {
statements: stmts,
terminator: Some(Terminator {
kind: TerminatorKind::Call {
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
args: vec![Operand::Move(ptr_tmp)],
args: args,
destination: Some((unit_temp, target)),
cleanup: None
}, // FIXME(#43234)
Expand Down

0 comments on commit 6614fa0

Please sign in to comment.