diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index c0372d24ed501..f59c9f7fd61cb 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -16,7 +16,7 @@ issue = "32838")] use core::intrinsics::{min_align_of_val, size_of_val}; -use core::ptr::NonNull; +use core::ptr::{NonNull, Unique}; use core::usize; #[doc(inline)] @@ -152,9 +152,17 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } } -#[cfg_attr(not(test), lang = "box_free")] +#[cfg(stage0)] +#[lang = "box_free"] +#[inline] +unsafe fn old_box_free(ptr: *mut T) { + box_free(Unique::new_unchecked(ptr)) +} + +#[cfg_attr(not(any(test, stage0)), lang = "box_free")] #[inline] -pub(crate) unsafe fn box_free(ptr: *mut T) { +pub(crate) unsafe fn box_free(ptr: Unique) { + let ptr = ptr.as_ptr(); let size = size_of_val(&*ptr); let align = min_align_of_val(&*ptr); // We do not allocate for Box when T is ZST, so deallocation is also not necessary. diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index e52a0216dd329..d0950bff9ce80 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -566,7 +566,8 @@ impl Arc { fn from_box(v: Box) -> Arc { unsafe { - let bptr = Box::into_raw(v); + let box_unique = Box::into_unique(v); + let bptr = box_unique.as_ptr(); let value_size = size_of_val(&*bptr); let ptr = Self::allocate_for_ptr(bptr); @@ -578,7 +579,7 @@ impl Arc { value_size); // Free the allocation without dropping its contents - box_free(bptr); + box_free(box_unique); Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 8fb8e111754a9..d0188c6e82858 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -681,7 +681,8 @@ impl Rc { fn from_box(v: Box) -> Rc { unsafe { - let bptr = Box::into_raw(v); + let box_unique = Box::into_unique(v); + let bptr = box_unique.as_ptr(); let value_size = size_of_val(&*bptr); let ptr = Self::allocate_for_ptr(bptr); @@ -693,7 +694,7 @@ impl Rc { value_size); // Free the allocation without dropping its contents - box_free(bptr); + box_free(box_unique); Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d38c003ef8aeb..c28fcfe88059f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -34,7 +34,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::{self, Mir, interpret}; use mir::interpret::{Value, PrimVal}; -use ty::subst::{Kind, Substs}; +use ty::subst::{Kind, Substs, Subst}; use ty::ReprOptions; use ty::Instance; use traits; @@ -2328,7 +2328,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); let adt_def = self.adt_def(def_id); - let substs = self.mk_substs(iter::once(Kind::from(ty))); + let generics = self.generics_of(def_id); + let mut substs = vec![Kind::from(ty)]; + // Add defaults for other generic params if there are some. + for def in generics.types.iter().skip(1) { + assert!(def.has_default); + let ty = self.type_of(def.def_id).subst(self, &substs); + substs.push(ty.into()); + } + let substs = self.mk_substs(substs.into_iter()); self.mk_ty(TyAdt(adt_def, substs)) } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index ec7ee466008a5..0ed95a319f7de 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -918,11 +918,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { )); } - if self.is_box_free(func) { - self.check_box_free_inputs(mir, term, &sig, args, term_location); - } else { - self.check_call_inputs(mir, term, &sig, args, term_location); - } + self.check_call_inputs(mir, term, &sig, args, term_location); } TerminatorKind::Assert { ref cond, ref msg, .. @@ -1026,70 +1022,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn is_box_free(&self, operand: &Operand<'tcx>) -> bool { - match *operand { - Operand::Constant(ref c) => match c.ty.sty { - ty::TyFnDef(ty_def_id, _) => { - Some(ty_def_id) == self.tcx().lang_items().box_free_fn() - } - _ => false, - }, - _ => false, - } - } - - fn check_box_free_inputs( - &mut self, - mir: &Mir<'tcx>, - term: &Terminator<'tcx>, - sig: &ty::FnSig<'tcx>, - args: &[Operand<'tcx>], - term_location: Location, - ) { - debug!("check_box_free_inputs"); - - // box_free takes a Box as a pointer. Allow for that. - - if sig.inputs().len() != 1 { - span_mirbug!(self, term, "box_free should take 1 argument"); - return; - } - - let pointee_ty = match sig.inputs()[0].sty { - ty::TyRawPtr(mt) => mt.ty, - _ => { - span_mirbug!(self, term, "box_free should take a raw ptr"); - return; - } - }; - - if args.len() != 1 { - span_mirbug!(self, term, "box_free called with wrong # of args"); - return; - } - - let ty = args[0].ty(mir, self.tcx()); - let arg_ty = match ty.sty { - ty::TyRawPtr(mt) => mt.ty, - ty::TyAdt(def, _) if def.is_box() => ty.boxed_ty(), - _ => { - span_mirbug!(self, term, "box_free called with bad arg ty"); - return; - } - }; - - if let Err(terr) = self.sub_types(arg_ty, pointee_ty, term_location.at_self()) { - span_mirbug!( - self, - term, - "bad box_free arg ({:?} <- {:?}): {:?}", - pointee_ty, - arg_ty, - terr - ); - } - } - fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) { let is_cleanup = block_data.is_cleanup; self.last_span = block_data.terminator().source_info.span; diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2b491385d661d..b743cccd36c5a 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -379,8 +379,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { debug!("Inlined {:?} into {:?}", callsite.callee, self.source); - let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn(); - let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len()); let mut promoted_map = IndexVec::with_capacity(callee_mir.promoted.len()); @@ -460,24 +458,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let return_block = destination.1; - let args : Vec<_> = if is_box_free { - assert!(args.len() == 1); - // box_free takes a Box, but is defined with a *mut T, inlining - // needs to generate the cast. - // FIXME: we should probably just generate correct MIR in the first place... - - let arg = if let Operand::Move(ref place) = args[0] { - place.clone() - } else { - bug!("Constant arg to \"box_free\""); - }; - - let ptr_ty = args[0].ty(caller_mir, self.tcx); - vec![self.cast_box_free_arg(arg, ptr_ty, &callsite, caller_mir)] - } else { - // Copy the arguments if needed. - self.make_call_args(args, &callsite, caller_mir) - }; + // Copy the arguments if needed. + let args: Vec<_> = self.make_call_args(args, &callsite, caller_mir); let bb_len = caller_mir.basic_blocks().len(); let mut integrator = Integrator { @@ -518,49 +500,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } } - fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>, - callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local { - let arg = Rvalue::Ref( - self.tcx.types.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - arg.deref()); - - let ty = arg.ty(caller_mir, self.tcx); - let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span); - let ref_tmp = caller_mir.local_decls.push(ref_tmp); - let ref_tmp = Place::Local(ref_tmp); - - let ref_stmt = Statement { - source_info: callsite.location, - kind: StatementKind::Assign(ref_tmp.clone(), arg) - }; - - caller_mir[callsite.bb] - .statements.push(ref_stmt); - - let pointee_ty = match ptr_ty.sty { - ty::TyRawPtr(tm) | ty::TyRef(_, tm) => tm.ty, - _ if ptr_ty.is_box() => ptr_ty.boxed_ty(), - _ => bug!("Invalid type `{:?}` for call to box_free", ptr_ty) - }; - let ptr_ty = self.tcx.mk_mut_ptr(pointee_ty); - - let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Move(ref_tmp), ptr_ty); - - let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span); - let cast_tmp = caller_mir.local_decls.push(cast_tmp); - - let cast_stmt = Statement { - source_info: callsite.location, - kind: StatementKind::Assign(Place::Local(cast_tmp), raw_ptr) - }; - - caller_mir[callsite.bb] - .statements.push(cast_stmt); - - cast_tmp - } - fn make_call_args( &self, args: Vec>, diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index e5719407da639..4b7c581d3c8ff 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -339,18 +339,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) @@ -793,11 +794,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) @@ -860,28 +862,34 @@ 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 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(); let call = TerminatorKind::Call { func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), - args: vec![Operand::Move(self.place.clone())], + args: args, destination: Some((unit_temp, target)), cleanup: None }; // FIXME(#43234)