Skip to content

Commit a5c6cb8

Browse files
committed
remove box_free and replace with drop impl
1 parent 0966f32 commit a5c6cb8

File tree

17 files changed

+91
-146
lines changed

17 files changed

+91
-146
lines changed

compiler/rustc_codegen_cranelift/example/mini_core.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,8 @@ impl<T> Box<T> {
546546

547547
impl<T: ?Sized, A> Drop for Box<T, A> {
548548
fn drop(&mut self) {
549-
// drop is currently performed by compiler.
549+
// inner value is dropped by compiler
550+
libc::free(self.0.pointer.0 as *mut u8);
550551
}
551552
}
552553

@@ -563,11 +564,6 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
563564
libc::malloc(size)
564565
}
565566

566-
#[lang = "box_free"]
567-
unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, _alloc: ()) {
568-
libc::free(ptr.pointer.0 as *mut u8);
569-
}
570-
571567
#[lang = "drop"]
572568
pub trait Drop {
573569
fn drop(&mut self);

compiler/rustc_codegen_gcc/example/mini_core.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,8 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> fo
490490

491491
impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
492492
fn drop(&mut self) {
493-
// drop is currently performed by compiler.
493+
// inner value is dropped by compiler
494+
libc::free(self.pointer.0 as *mut u8);
494495
}
495496
}
496497

@@ -507,11 +508,6 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
507508
libc::malloc(size)
508509
}
509510

510-
#[lang = "box_free"]
511-
unsafe fn box_free<T: ?Sized>(ptr: Unique<T>, _alloc: ()) {
512-
libc::free(ptr.pointer.0 as *mut u8);
513-
}
514-
515511
#[lang = "drop"]
516512
pub trait Drop {
517513
fn drop(&mut self);

compiler/rustc_hir/src/lang_items.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ language_item_table! {
250250
FormatUnsafeArg, sym::format_unsafe_arg, format_unsafe_arg, Target::Struct, GenericRequirement::None;
251251

252252
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
253-
BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
254253
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
255254
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
256255

compiler/rustc_mir_dataflow/src/elaborate_drops.rs

Lines changed: 26 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,15 @@ where
409409
self.drop_ladder(fields, succ, unwind).0
410410
}
411411

412+
/// Drops the T contained in a `Box<T>` if it has not been moved out of
412413
#[instrument(level = "debug", ret)]
413-
fn open_drop_for_box(&mut self, adt: ty::AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> BasicBlock {
414+
fn open_drop_for_box_contents(
415+
&mut self,
416+
adt: ty::AdtDef<'tcx>,
417+
substs: SubstsRef<'tcx>,
418+
succ: BasicBlock,
419+
unwind: Unwind,
420+
) -> BasicBlock {
414421
// drop glue is sent straight to codegen
415422
// box cannot be directly dereferenced
416423
let unique_ty = adt.non_enum_variant().fields[FieldIdx::new(0)].ty(self.tcx(), substs);
@@ -425,11 +432,7 @@ where
425432

426433
let interior_path = self.elaborator.deref_subpath(self.path);
427434

428-
let succ = self.box_free_block(adt, substs, self.succ, self.unwind);
429-
let unwind_succ =
430-
self.unwind.map(|unwind| self.box_free_block(adt, substs, unwind, Unwind::InCleanup));
431-
432-
self.drop_subpath(interior, interior_path, succ, unwind_succ)
435+
self.drop_subpath(interior, interior_path, succ, unwind)
433436
}
434437

435438
#[instrument(level = "debug", ret)]
@@ -453,7 +456,15 @@ where
453456
self.open_drop_for_adt_contents(adt, substs)
454457
};
455458

456-
if adt.has_dtor(self.tcx()) {
459+
if adt.is_box() {
460+
// we need to drop the inside of the box before running the destructor
461+
let succ = self.destructor_call_block(contents_drop);
462+
let unwind = contents_drop
463+
.1
464+
.map(|unwind| self.destructor_call_block((unwind, Unwind::InCleanup)));
465+
466+
self.open_drop_for_box_contents(adt, substs, succ, unwind)
467+
} else if adt.has_dtor(self.tcx()) {
457468
self.destructor_call_block(contents_drop)
458469
} else {
459470
contents_drop.0
@@ -650,7 +661,13 @@ where
650661
}),
651662
is_cleanup: unwind.is_cleanup(),
652663
};
653-
self.elaborator.patch().new_block(result)
664+
665+
let destructor_block = self.elaborator.patch().new_block(result);
666+
667+
let block_start = Location { block: destructor_block, statement_index: 0 };
668+
self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow);
669+
670+
self.drop_flag_test_block(destructor_block, succ, unwind)
654671
}
655672

656673
/// Create a loop that drops an array:
@@ -851,13 +868,7 @@ where
851868
self.open_drop_for_tuple(&tys)
852869
}
853870
ty::Tuple(fields) => self.open_drop_for_tuple(fields),
854-
ty::Adt(def, substs) => {
855-
if def.is_box() {
856-
self.open_drop_for_box(*def, substs)
857-
} else {
858-
self.open_drop_for_adt(*def, substs)
859-
}
860-
}
871+
ty::Adt(def, substs) => self.open_drop_for_adt(*def, substs),
861872
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
862873
ty::Array(ety, size) => {
863874
let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
@@ -905,65 +916,6 @@ where
905916
blk
906917
}
907918

908-
/// Creates a block that frees the backing memory of a `Box` if its drop is required (either
909-
/// statically or by checking its drop flag).
910-
///
911-
/// The contained value will not be dropped.
912-
fn box_free_block(
913-
&mut self,
914-
adt: ty::AdtDef<'tcx>,
915-
substs: SubstsRef<'tcx>,
916-
target: BasicBlock,
917-
unwind: Unwind,
918-
) -> BasicBlock {
919-
let block = self.unelaborated_free_block(adt, substs, target, unwind);
920-
self.drop_flag_test_block(block, target, unwind)
921-
}
922-
923-
/// Creates a block that frees the backing memory of a `Box` (without dropping the contained
924-
/// value).
925-
fn unelaborated_free_block(
926-
&mut self,
927-
adt: ty::AdtDef<'tcx>,
928-
substs: SubstsRef<'tcx>,
929-
target: BasicBlock,
930-
unwind: Unwind,
931-
) -> BasicBlock {
932-
let tcx = self.tcx();
933-
let unit_temp = Place::from(self.new_temp(tcx.mk_unit()));
934-
let free_func = tcx.require_lang_item(LangItem::BoxFree, Some(self.source_info.span));
935-
let args = adt
936-
.variant(FIRST_VARIANT)
937-
.fields
938-
.iter()
939-
.enumerate()
940-
.map(|(i, f)| {
941-
let field = FieldIdx::new(i);
942-
let field_ty = f.ty(tcx, substs);
943-
Operand::Move(tcx.mk_place_field(self.place, field, field_ty))
944-
})
945-
.collect();
946-
947-
let call = TerminatorKind::Call {
948-
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
949-
args,
950-
destination: unit_temp,
951-
target: Some(target),
952-
unwind: if unwind.is_cleanup() {
953-
UnwindAction::Terminate
954-
} else {
955-
UnwindAction::Continue
956-
},
957-
from_hir_call: false,
958-
fn_span: self.source_info.span,
959-
}; // FIXME(#43234)
960-
let free_block = self.new_block(unwind, call);
961-
962-
let block_start = Location { block: free_block, statement_index: 0 };
963-
self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow);
964-
free_block
965-
}
966-
967919
fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
968920
let block = TerminatorKind::Drop {
969921
place: self.place,

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,6 @@
123123
//! pointers to these functions even if they never get called anywhere. This can
124124
//! be seen as a special case of taking a function reference.
125125
//!
126-
//! #### Boxes
127-
//! Since `Box` expression have special compiler support, no explicit calls to
128-
//! `exchange_malloc()` and `box_free()` may show up in MIR, even if the
129-
//! compiler will generate them. We have to observe `Rvalue::Box` expressions
130-
//! and Box-typed drop-statements for that purpose.
131-
//!
132126
//!
133127
//! Interaction with Cross-Crate Inlining
134128
//! -------------------------------------

compiler/rustc_span/src/symbol.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,6 @@ symbols! {
432432
bool,
433433
borrowck_graphviz_format,
434434
borrowck_graphviz_postflow,
435-
box_free,
436435
box_new,
437436
box_patterns,
438437
box_syntax,

library/alloc/src/alloc.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
#[cfg(not(test))]
66
use core::intrinsics;
7+
#[cfg(all(bootstrap, not(test)))]
78
use core::intrinsics::{min_align_of_val, size_of_val};
89

10+
#[cfg(all(bootstrap, not(test)))]
911
use core::ptr::Unique;
1012
#[cfg(not(test))]
1113
use core::ptr::{self, NonNull};
@@ -335,14 +337,15 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
335337
}
336338
}
337339

338-
#[cfg_attr(not(test), lang = "box_free")]
340+
#[cfg(all(bootstrap, not(test)))]
341+
#[lang = "box_free"]
339342
#[inline]
340343
// This signature has to be the same as `Box`, otherwise an ICE will happen.
341344
// When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as
342345
// well.
343346
// For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`,
344347
// this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well.
345-
pub(crate) unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) {
348+
unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: Unique<T>, alloc: A) {
346349
unsafe {
347350
let size = size_of_val(ptr.as_ref());
348351
let align = min_align_of_val(ptr.as_ref());

library/alloc/src/boxed.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1211,8 +1211,16 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
12111211

12121212
#[stable(feature = "rust1", since = "1.0.0")]
12131213
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
1214+
#[inline]
12141215
fn drop(&mut self) {
1215-
// FIXME: Do nothing, drop is currently performed by compiler.
1216+
// the T in the Box is dropped by the compiler before the destructor is run
1217+
1218+
let ptr = self.0;
1219+
1220+
unsafe {
1221+
let layout = Layout::for_value_raw(ptr.as_ptr());
1222+
self.1.deallocate(From::from(ptr.cast()), layout)
1223+
}
12161224
}
12171225
}
12181226

library/alloc/src/rc.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ use core::slice::from_raw_parts_mut;
270270
#[cfg(not(no_global_oom_handling))]
271271
use crate::alloc::handle_alloc_error;
272272
#[cfg(not(no_global_oom_handling))]
273-
use crate::alloc::{box_free, WriteCloneIntoRaw};
273+
use crate::alloc::WriteCloneIntoRaw;
274274
use crate::alloc::{AllocError, Allocator, Global, Layout};
275275
use crate::borrow::{Cow, ToOwned};
276276
#[cfg(not(no_global_oom_handling))]
@@ -1442,23 +1442,21 @@ impl<T: ?Sized> Rc<T> {
14421442
}
14431443

14441444
#[cfg(not(no_global_oom_handling))]
1445-
fn from_box(v: Box<T>) -> Rc<T> {
1445+
fn from_box(src: Box<T>) -> Rc<T> {
14461446
unsafe {
1447-
let (box_unique, alloc) = Box::into_unique(v);
1448-
let bptr = box_unique.as_ptr();
1449-
1450-
let value_size = size_of_val(&*bptr);
1451-
let ptr = Self::allocate_for_ptr(bptr);
1447+
let value_size = size_of_val(&*src);
1448+
let ptr = Self::allocate_for_ptr(&*src);
14521449

14531450
// Copy value as bytes
14541451
ptr::copy_nonoverlapping(
1455-
bptr as *const T as *const u8,
1452+
&*src as *const T as *const u8,
14561453
&mut (*ptr).value as *mut _ as *mut u8,
14571454
value_size,
14581455
);
14591456

14601457
// Free the allocation without dropping its contents
1461-
box_free(box_unique, alloc);
1458+
let src = Box::from_raw(Box::into_raw(src) as *mut mem::ManuallyDrop<T>);
1459+
drop(src);
14621460

14631461
Self::from_ptr(ptr)
14641462
}

library/alloc/src/sync.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
3333
#[cfg(not(no_global_oom_handling))]
3434
use crate::alloc::handle_alloc_error;
3535
#[cfg(not(no_global_oom_handling))]
36-
use crate::alloc::{box_free, WriteCloneIntoRaw};
36+
use crate::alloc::WriteCloneIntoRaw;
3737
use crate::alloc::{AllocError, Allocator, Global, Layout};
3838
use crate::borrow::{Cow, ToOwned};
3939
use crate::boxed::Box;
@@ -1360,23 +1360,21 @@ impl<T: ?Sized> Arc<T> {
13601360
}
13611361

13621362
#[cfg(not(no_global_oom_handling))]
1363-
fn from_box(v: Box<T>) -> Arc<T> {
1363+
fn from_box(src: Box<T>) -> Arc<T> {
13641364
unsafe {
1365-
let (box_unique, alloc) = Box::into_unique(v);
1366-
let bptr = box_unique.as_ptr();
1367-
1368-
let value_size = size_of_val(&*bptr);
1369-
let ptr = Self::allocate_for_ptr(bptr);
1365+
let value_size = size_of_val(&*src);
1366+
let ptr = Self::allocate_for_ptr(&*src);
13701367

13711368
// Copy value as bytes
13721369
ptr::copy_nonoverlapping(
1373-
bptr as *const T as *const u8,
1370+
&*src as *const T as *const u8,
13741371
&mut (*ptr).data as *mut _ as *mut u8,
13751372
value_size,
13761373
);
13771374

13781375
// Free the allocation without dropping its contents
1379-
box_free(box_unique, alloc);
1376+
let src = Box::from_raw(Box::into_raw(src) as *mut mem::ManuallyDrop<T>);
1377+
drop(src);
13801378

13811379
Self::from_ptr(ptr)
13821380
}

0 commit comments

Comments
 (0)