Skip to content

Commit 6614fa0

Browse files
committed
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.
1 parent dfa6111 commit 6614fa0

File tree

1 file changed

+44
-24
lines changed

1 file changed

+44
-24
lines changed

src/librustc_mir/util/elaborate_drops.rs

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -337,18 +337,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
337337
self.drop_ladder(fields, succ, unwind).0
338338
}
339339

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

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

347348
let succ = self.succ; // FIXME(#43234)
348349
let unwind = self.unwind;
349-
let succ = self.box_free_block(ty, succ, unwind);
350+
let succ = self.box_free_block(adt, substs, succ, unwind);
350351
let unwind_succ = self.unwind.map(|unwind| {
351-
self.box_free_block(ty, unwind, Unwind::InCleanup)
352+
self.box_free_block(adt, substs, unwind, Unwind::InCleanup)
352353
});
353354

354355
self.drop_subpath(&interior, interior_path, succ, unwind_succ)
@@ -791,11 +792,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
791792
ty::TyTuple(tys) => {
792793
self.open_drop_for_tuple(tys)
793794
}
794-
ty::TyAdt(def, _) if def.is_box() => {
795-
self.open_drop_for_box(ty.boxed_ty())
796-
}
797795
ty::TyAdt(def, substs) => {
798-
self.open_drop_for_adt(def, substs)
796+
if def.is_box() {
797+
self.open_drop_for_box(def, substs)
798+
} else {
799+
self.open_drop_for_adt(def, substs)
800+
}
799801
}
800802
ty::TyDynamic(..) => {
801803
let unwind = self.unwind; // FIXME(#43234)
@@ -858,34 +860,40 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
858860

859861
fn box_free_block<'a>(
860862
&mut self,
861-
ty: Ty<'tcx>,
863+
adt: &'tcx ty::AdtDef,
864+
substs: &'tcx Substs<'tcx>,
862865
target: BasicBlock,
863866
unwind: Unwind,
864867
) -> BasicBlock {
865-
let block = self.unelaborated_free_block(ty, target, unwind);
868+
let block = self.unelaborated_free_block(adt, substs, target, unwind);
866869
self.drop_flag_test_block(block, target, unwind)
867870
}
868871

869872
fn unelaborated_free_block<'a>(
870873
&mut self,
871-
ty: Ty<'tcx>,
874+
adt: &'tcx ty::AdtDef,
875+
substs: &'tcx Substs<'tcx>,
872876
target: BasicBlock,
873877
unwind: Unwind
874878
) -> BasicBlock {
875879
let tcx = self.tcx();
876880
let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
877881
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
878-
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
879-
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
880-
ty: ty,
881-
mutbl: hir::Mutability::MutMutable
882-
});
883-
let ptr_ty = tcx.mk_mut_ptr(ty);
884-
let ref_tmp = Place::Local(self.new_temp(ref_ty));
885-
let ptr_tmp = Place::Local(self.new_temp(ptr_ty));
886-
887-
let free_block = BasicBlockData {
888-
statements: vec![
882+
let free_sig = tcx.fn_sig(free_func).skip_binder().clone();
883+
let free_inputs = free_sig.inputs();
884+
// If the box_free function takes a *mut T, transform the Box into
885+
// such a pointer before calling box_free. Otherwise, pass it all
886+
// the fields in the Box as individual arguments.
887+
let (stmts, args) = if free_inputs.len() == 1 && free_inputs[0].is_mutable_pointer() {
888+
let ty = substs.type_at(0);
889+
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
890+
ty: ty,
891+
mutbl: hir::Mutability::MutMutable
892+
});
893+
let ptr_ty = tcx.mk_mut_ptr(ty);
894+
let ref_tmp = Place::Local(self.new_temp(ref_ty));
895+
let ptr_tmp = Place::Local(self.new_temp(ptr_ty));
896+
let stmts = vec![
889897
self.assign(&ref_tmp, Rvalue::Ref(
890898
tcx.types.re_erased,
891899
BorrowKind::Mut { allow_two_phase_borrow: false },
@@ -896,11 +904,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
896904
Operand::Move(ref_tmp),
897905
ptr_ty,
898906
)),
899-
],
907+
];
908+
(stmts, vec![Operand::Move(ptr_tmp)])
909+
} else {
910+
let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
911+
let field = Field::new(i);
912+
let field_ty = f.ty(self.tcx(), substs);
913+
Operand::Move(self.place.clone().field(field, field_ty))
914+
}).collect();
915+
(vec![], args)
916+
};
917+
918+
let free_block = BasicBlockData {
919+
statements: stmts,
900920
terminator: Some(Terminator {
901921
kind: TerminatorKind::Call {
902922
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
903-
args: vec![Operand::Move(ptr_tmp)],
923+
args: args,
904924
destination: Some((unit_temp, target)),
905925
cleanup: None
906926
}, // FIXME(#43234)

0 commit comments

Comments
 (0)