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

+2-6
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

+2-6
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

-1
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

+26-74
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

-6
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

-1
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

+5-2
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

+9-1
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

+7-9
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

+7-9
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
}

src/doc/unstable-book/src/language-features/lang-items.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ it exists. The marker is the attribute `#[lang = "..."]` and there are
1111
various different values of `...`, i.e. various different 'lang
1212
items'.
1313

14-
For example, `Box` pointers require two lang items, one for allocation
15-
and one for deallocation. A freestanding program that uses the `Box`
14+
For example, `Box` pointers require a lang item for allocation.
15+
A freestanding program that uses the `Box`
1616
sugar for dynamic allocations via `malloc` and `free`:
1717

1818
```rust,ignore (libc-is-finicky)
@@ -48,9 +48,10 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
4848
p
4949
}
5050
51-
#[lang = "box_free"]
52-
unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
53-
libc::free(ptr as *mut libc::c_void)
51+
impl<T> Drop for Box<T> {
52+
fn drop(&mut self) {
53+
libc::free(self.0.0.0 as *mut libc::c_void)
54+
}
5455
}
5556
5657
#[start]
@@ -84,8 +85,8 @@ Other features provided by lang items include:
8485
`contravariant_lifetime`, etc.
8586

8687
Lang items are loaded lazily by the compiler; e.g. if one never uses
87-
`Box` then there is no need to define functions for `exchange_malloc`
88-
and `box_free`. `rustc` will emit an error when an item is needed
88+
`Box` then there is no need to define a function for `exchange_malloc`.
89+
`rustc` will emit an error when an item is needed
8990
but not found in the current crate or any that it depends on.
9091

9192
Most lang items are defined by `libcore`, but if you're trying to build
@@ -250,7 +251,6 @@ the source code.
250251
- Allocations
251252
- `owned_box`: `liballoc/boxed.rs`
252253
- `exchange_malloc`: `liballoc/heap.rs`
253-
- `box_free`: `liballoc/heap.rs`
254254
- Operands
255255
- `not`: `libcore/ops/bit.rs`
256256
- `bitand`: `libcore/ops/bit.rs`

src/tools/miri/tests/fail/alloc/stack_free.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
99
= note: BACKTRACE:
1010
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
1111
= note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at RUSTLIB/alloc/src/alloc.rs:LL:CC
12-
= note: inside `alloc::alloc::box_free::<i32, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
12+
= note: inside `<std::boxed::Box<i32> as std::ops::Drop>::drop` at RUSTLIB/alloc/src/boxed.rs:LL:CC
1313
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
1414
= note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
1515
note: inside `main`

0 commit comments

Comments
 (0)