diff options
| author | Mike Hommey <mh@glandium.org> | 2018-04-19 15:26:16 +0900 |
|---|---|---|
| committer | Mike Hommey <mh@glandium.org> | 2018-04-20 09:43:52 +0900 |
| commit | 6614fa0981f5d5555f7cd2f11e258fe989e98032 (patch) | |
| tree | 9b48866d5f3ff114b8944ecf89d46e2a16411c93 | |
| parent | dfa611146c7acd692f760619d25bfabf7261eaf5 (diff) | |
| download | rust-6614fa0981f5d5555f7cd2f11e258fe989e98032.tar.gz rust-6614fa0981f5d5555f7cd2f11e258fe989e98032.zip | |
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.
| -rw-r--r-- | src/librustc_mir/util/elaborate_drops.rs | 68 |
1 files changed, 44 insertions, 24 deletions
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 1564db1ee2a..cc91bbf9061 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -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) |
