Support an alternative form for box_free
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.
This commit is contained in:
parent
dfa611146c
commit
6614fa0981
1 changed files with 44 additions and 24 deletions
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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 },
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue