Skip to content

Commit 71d3dac

Browse files
committed
Auto merge of #50097 - glandium:box_free, r=nikomatsakis
Partial future-proofing for Box<T, A> In some ways, this is similar to @eddyb's PR #47043 that went stale, but doesn't cover everything. Notably, this still leaves Box internalized as a pointer in places, so practically speaking, only ZSTs can be practically added to the Box type with the changes here (the compiler ICEs otherwise). The Box type is not changed here, that's left for the future because I want to test that further first, but this puts things in place in a way that hopefully will make things easier.
2 parents ada45fd + bd8c177 commit 71d3dac

File tree

7 files changed

+51
-154
lines changed

7 files changed

+51
-154
lines changed

src/liballoc/alloc.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
issue = "32838")]
1717

1818
use core::intrinsics::{min_align_of_val, size_of_val};
19-
use core::ptr::NonNull;
19+
use core::ptr::{NonNull, Unique};
2020
use core::usize;
2121

2222
#[doc(inline)]
@@ -152,9 +152,17 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
152152
}
153153
}
154154

155-
#[cfg_attr(not(test), lang = "box_free")]
155+
#[cfg(stage0)]
156+
#[lang = "box_free"]
157+
#[inline]
158+
unsafe fn old_box_free<T: ?Sized>(ptr: *mut T) {
159+
box_free(Unique::new_unchecked(ptr))
160+
}
161+
162+
#[cfg_attr(not(any(test, stage0)), lang = "box_free")]
156163
#[inline]
157-
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
164+
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
165+
let ptr = ptr.as_ptr();
158166
let size = size_of_val(&*ptr);
159167
let align = min_align_of_val(&*ptr);
160168
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.

src/liballoc/arc.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,8 @@ impl<T: ?Sized> Arc<T> {
566566

567567
fn from_box(v: Box<T>) -> Arc<T> {
568568
unsafe {
569-
let bptr = Box::into_raw(v);
569+
let box_unique = Box::into_unique(v);
570+
let bptr = box_unique.as_ptr();
570571

571572
let value_size = size_of_val(&*bptr);
572573
let ptr = Self::allocate_for_ptr(bptr);
@@ -578,7 +579,7 @@ impl<T: ?Sized> Arc<T> {
578579
value_size);
579580

580581
// Free the allocation without dropping its contents
581-
box_free(bptr);
582+
box_free(box_unique);
582583

583584
Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
584585
}

src/liballoc/rc.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,8 @@ impl<T: ?Sized> Rc<T> {
681681

682682
fn from_box(v: Box<T>) -> Rc<T> {
683683
unsafe {
684-
let bptr = Box::into_raw(v);
684+
let box_unique = Box::into_unique(v);
685+
let bptr = box_unique.as_ptr();
685686

686687
let value_size = size_of_val(&*bptr);
687688
let ptr = Self::allocate_for_ptr(bptr);
@@ -693,7 +694,7 @@ impl<T: ?Sized> Rc<T> {
693694
value_size);
694695

695696
// Free the allocation without dropping its contents
696-
box_free(bptr);
697+
box_free(box_unique);
697698

698699
Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
699700
}

src/librustc/ty/context.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
3434
use middle::stability;
3535
use mir::{self, Mir, interpret};
3636
use mir::interpret::{Value, PrimVal};
37-
use ty::subst::{Kind, Substs};
37+
use ty::subst::{Kind, Substs, Subst};
3838
use ty::ReprOptions;
3939
use ty::Instance;
4040
use traits;
@@ -2328,7 +2328,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23282328
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
23292329
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
23302330
let adt_def = self.adt_def(def_id);
2331-
let substs = self.mk_substs(iter::once(Kind::from(ty)));
2331+
let generics = self.generics_of(def_id);
2332+
let mut substs = vec![Kind::from(ty)];
2333+
// Add defaults for other generic params if there are some.
2334+
for def in generics.types.iter().skip(1) {
2335+
assert!(def.has_default);
2336+
let ty = self.type_of(def.def_id).subst(self, &substs);
2337+
substs.push(ty.into());
2338+
}
2339+
let substs = self.mk_substs(substs.into_iter());
23322340
self.mk_ty(TyAdt(adt_def, substs))
23332341
}
23342342

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+1-69
Original file line numberDiff line numberDiff line change
@@ -918,11 +918,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
918918
));
919919
}
920920

921-
if self.is_box_free(func) {
922-
self.check_box_free_inputs(mir, term, &sig, args, term_location);
923-
} else {
924-
self.check_call_inputs(mir, term, &sig, args, term_location);
925-
}
921+
self.check_call_inputs(mir, term, &sig, args, term_location);
926922
}
927923
TerminatorKind::Assert {
928924
ref cond, ref msg, ..
@@ -1026,70 +1022,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
10261022
}
10271023
}
10281024

1029-
fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
1030-
match *operand {
1031-
Operand::Constant(ref c) => match c.ty.sty {
1032-
ty::TyFnDef(ty_def_id, _) => {
1033-
Some(ty_def_id) == self.tcx().lang_items().box_free_fn()
1034-
}
1035-
_ => false,
1036-
},
1037-
_ => false,
1038-
}
1039-
}
1040-
1041-
fn check_box_free_inputs(
1042-
&mut self,
1043-
mir: &Mir<'tcx>,
1044-
term: &Terminator<'tcx>,
1045-
sig: &ty::FnSig<'tcx>,
1046-
args: &[Operand<'tcx>],
1047-
term_location: Location,
1048-
) {
1049-
debug!("check_box_free_inputs");
1050-
1051-
// box_free takes a Box as a pointer. Allow for that.
1052-
1053-
if sig.inputs().len() != 1 {
1054-
span_mirbug!(self, term, "box_free should take 1 argument");
1055-
return;
1056-
}
1057-
1058-
let pointee_ty = match sig.inputs()[0].sty {
1059-
ty::TyRawPtr(mt) => mt.ty,
1060-
_ => {
1061-
span_mirbug!(self, term, "box_free should take a raw ptr");
1062-
return;
1063-
}
1064-
};
1065-
1066-
if args.len() != 1 {
1067-
span_mirbug!(self, term, "box_free called with wrong # of args");
1068-
return;
1069-
}
1070-
1071-
let ty = args[0].ty(mir, self.tcx());
1072-
let arg_ty = match ty.sty {
1073-
ty::TyRawPtr(mt) => mt.ty,
1074-
ty::TyAdt(def, _) if def.is_box() => ty.boxed_ty(),
1075-
_ => {
1076-
span_mirbug!(self, term, "box_free called with bad arg ty");
1077-
return;
1078-
}
1079-
};
1080-
1081-
if let Err(terr) = self.sub_types(arg_ty, pointee_ty, term_location.at_self()) {
1082-
span_mirbug!(
1083-
self,
1084-
term,
1085-
"bad box_free arg ({:?} <- {:?}): {:?}",
1086-
pointee_ty,
1087-
arg_ty,
1088-
terr
1089-
);
1090-
}
1091-
}
1092-
10931025
fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) {
10941026
let is_cleanup = block_data.is_cleanup;
10951027
self.last_span = block_data.terminator().source_info.span;

src/librustc_mir/transform/inline.rs

+2-63
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
379379
TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
380380
debug!("Inlined {:?} into {:?}", callsite.callee, self.source);
381381

382-
let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn();
383-
384382
let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len());
385383
let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len());
386384
let mut promoted_map = IndexVec::with_capacity(callee_mir.promoted.len());
@@ -460,24 +458,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
460458

461459
let return_block = destination.1;
462460

463-
let args : Vec<_> = if is_box_free {
464-
assert!(args.len() == 1);
465-
// box_free takes a Box, but is defined with a *mut T, inlining
466-
// needs to generate the cast.
467-
// FIXME: we should probably just generate correct MIR in the first place...
468-
469-
let arg = if let Operand::Move(ref place) = args[0] {
470-
place.clone()
471-
} else {
472-
bug!("Constant arg to \"box_free\"");
473-
};
474-
475-
let ptr_ty = args[0].ty(caller_mir, self.tcx);
476-
vec![self.cast_box_free_arg(arg, ptr_ty, &callsite, caller_mir)]
477-
} else {
478-
// Copy the arguments if needed.
479-
self.make_call_args(args, &callsite, caller_mir)
480-
};
461+
// Copy the arguments if needed.
462+
let args: Vec<_> = self.make_call_args(args, &callsite, caller_mir);
481463

482464
let bb_len = caller_mir.basic_blocks().len();
483465
let mut integrator = Integrator {
@@ -518,49 +500,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
518500
}
519501
}
520502

521-
fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>,
522-
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
523-
let arg = Rvalue::Ref(
524-
self.tcx.types.re_erased,
525-
BorrowKind::Mut { allow_two_phase_borrow: false },
526-
arg.deref());
527-
528-
let ty = arg.ty(caller_mir, self.tcx);
529-
let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span);
530-
let ref_tmp = caller_mir.local_decls.push(ref_tmp);
531-
let ref_tmp = Place::Local(ref_tmp);
532-
533-
let ref_stmt = Statement {
534-
source_info: callsite.location,
535-
kind: StatementKind::Assign(ref_tmp.clone(), arg)
536-
};
537-
538-
caller_mir[callsite.bb]
539-
.statements.push(ref_stmt);
540-
541-
let pointee_ty = match ptr_ty.sty {
542-
ty::TyRawPtr(tm) | ty::TyRef(_, tm) => tm.ty,
543-
_ if ptr_ty.is_box() => ptr_ty.boxed_ty(),
544-
_ => bug!("Invalid type `{:?}` for call to box_free", ptr_ty)
545-
};
546-
let ptr_ty = self.tcx.mk_mut_ptr(pointee_ty);
547-
548-
let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Move(ref_tmp), ptr_ty);
549-
550-
let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span);
551-
let cast_tmp = caller_mir.local_decls.push(cast_tmp);
552-
553-
let cast_stmt = Statement {
554-
source_info: callsite.location,
555-
kind: StatementKind::Assign(Place::Local(cast_tmp), raw_ptr)
556-
};
557-
558-
caller_mir[callsite.bb]
559-
.statements.push(cast_stmt);
560-
561-
cast_tmp
562-
}
563-
564503
fn make_call_args(
565504
&self,
566505
args: Vec<Operand<'tcx>>,

src/librustc_mir/util/elaborate_drops.rs

+21-13
Original file line numberDiff line numberDiff line change
@@ -339,18 +339,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
339339
self.drop_ladder(fields, succ, unwind).0
340340
}
341341

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

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

349350
let succ = self.succ; // FIXME(#43234)
350351
let unwind = self.unwind;
351-
let succ = self.box_free_block(ty, succ, unwind);
352+
let succ = self.box_free_block(adt, substs, succ, unwind);
352353
let unwind_succ = self.unwind.map(|unwind| {
353-
self.box_free_block(ty, unwind, Unwind::InCleanup)
354+
self.box_free_block(adt, substs, unwind, Unwind::InCleanup)
354355
});
355356

356357
self.drop_subpath(&interior, interior_path, succ, unwind_succ)
@@ -793,11 +794,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
793794
ty::TyTuple(tys) => {
794795
self.open_drop_for_tuple(tys)
795796
}
796-
ty::TyAdt(def, _) if def.is_box() => {
797-
self.open_drop_for_box(ty.boxed_ty())
798-
}
799797
ty::TyAdt(def, substs) => {
800-
self.open_drop_for_adt(def, substs)
798+
if def.is_box() {
799+
self.open_drop_for_box(def, substs)
800+
} else {
801+
self.open_drop_for_adt(def, substs)
802+
}
801803
}
802804
ty::TyDynamic(..) => {
803805
let unwind = self.unwind; // FIXME(#43234)
@@ -860,28 +862,34 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
860862

861863
fn box_free_block<'a>(
862864
&mut self,
863-
ty: Ty<'tcx>,
865+
adt: &'tcx ty::AdtDef,
866+
substs: &'tcx Substs<'tcx>,
864867
target: BasicBlock,
865868
unwind: Unwind,
866869
) -> BasicBlock {
867-
let block = self.unelaborated_free_block(ty, target, unwind);
870+
let block = self.unelaborated_free_block(adt, substs, target, unwind);
868871
self.drop_flag_test_block(block, target, unwind)
869872
}
870873

871874
fn unelaborated_free_block<'a>(
872875
&mut self,
873-
ty: Ty<'tcx>,
876+
adt: &'tcx ty::AdtDef,
877+
substs: &'tcx Substs<'tcx>,
874878
target: BasicBlock,
875879
unwind: Unwind
876880
) -> BasicBlock {
877881
let tcx = self.tcx();
878882
let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
879883
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
880-
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
884+
let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| {
885+
let field = Field::new(i);
886+
let field_ty = f.ty(self.tcx(), substs);
887+
Operand::Move(self.place.clone().field(field, field_ty))
888+
}).collect();
881889

882890
let call = TerminatorKind::Call {
883891
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
884-
args: vec![Operand::Move(self.place.clone())],
892+
args: args,
885893
destination: Some((unit_temp, target)),
886894
cleanup: None
887895
}; // FIXME(#43234)

0 commit comments

Comments
 (0)