Skip to content

Commit 8d50bcc

Browse files
committed
Auto merge of #153251 - scottmcm:deallocate-nonnull, r=joboet
Update `__rust_[rd]ealloc` to take `NonNull<u8>` instead of `*mut u8` Passing null to it is [already UB per Miri](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=8dcd25a549c11de72adc94a668277779) anyway, and this is ABI-compatible as `NonNull` is `repr(transparent)`. Inspired by #152702 (comment) ; Similar to #152605 which changed `align: usize` to `align: ptr::Alignment`.
2 parents ddd36bd + 2c6ec51 commit 8d50bcc

9 files changed

+76
-97
lines changed

library/alloc/src/alloc.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,16 @@ unsafe extern "Rust" {
2222
#[rustc_deallocator]
2323
#[rustc_nounwind]
2424
#[rustc_std_internal_symbol]
25-
fn __rust_dealloc(ptr: *mut u8, size: usize, align: Alignment);
25+
fn __rust_dealloc(ptr: NonNull<u8>, size: usize, align: Alignment);
2626
#[rustc_reallocator]
2727
#[rustc_nounwind]
2828
#[rustc_std_internal_symbol]
29-
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: Alignment, new_size: usize) -> *mut u8;
29+
fn __rust_realloc(
30+
ptr: NonNull<u8>,
31+
old_size: usize,
32+
align: Alignment,
33+
new_size: usize,
34+
) -> *mut u8;
3035
#[rustc_allocator_zeroed]
3136
#[rustc_nounwind]
3237
#[rustc_std_internal_symbol]
@@ -112,6 +117,13 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
112117
#[inline]
113118
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
114119
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
120+
unsafe { dealloc_nonnull(NonNull::new_unchecked(ptr), layout) }
121+
}
122+
123+
/// Same as [`dealloc`] but when you already have a non-null pointer
124+
#[inline]
125+
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
126+
unsafe fn dealloc_nonnull(ptr: NonNull<u8>, layout: Layout) {
115127
unsafe { __rust_dealloc(ptr, layout.size(), layout.alignment()) }
116128
}
117129

@@ -132,6 +144,13 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
132144
#[inline]
133145
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
134146
pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
147+
unsafe { realloc_nonnull(NonNull::new_unchecked(ptr), layout, new_size) }
148+
}
149+
150+
/// Same as [`realloc`] but when you already have a non-null pointer
151+
#[inline]
152+
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
153+
unsafe fn realloc_nonnull(ptr: NonNull<u8>, layout: Layout, new_size: usize) -> *mut u8 {
135154
unsafe { __rust_realloc(ptr, layout.size(), layout.alignment(), new_size) }
136155
}
137156

@@ -206,7 +225,7 @@ impl Global {
206225
// allocation than requested.
207226
// * Other conditions must be upheld by the caller, as per `Allocator::deallocate()`'s
208227
// safety documentation.
209-
unsafe { dealloc(ptr.as_ptr(), layout) }
228+
unsafe { dealloc_nonnull(ptr, layout) }
210229
}
211230
}
212231

@@ -236,7 +255,7 @@ impl Global {
236255
// `realloc` probably checks for `new_size >= old_layout.size()` or something similar.
237256
hint::assert_unchecked(new_size >= old_layout.size());
238257

239-
let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
258+
let raw_ptr = realloc_nonnull(ptr, old_layout, new_size);
240259
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
241260
if zeroed {
242261
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
@@ -285,7 +304,7 @@ impl Global {
285304
// `realloc` probably checks for `new_size <= old_layout.size()` or something similar.
286305
hint::assert_unchecked(new_size <= old_layout.size());
287306

288-
let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
307+
let raw_ptr = realloc_nonnull(ptr, old_layout, new_size);
289308
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
290309
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
291310
},

tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-abort.mir

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
1212
scope 17 (inlined Layout::size) {
1313
}
1414
scope 18 (inlined std::ptr::Unique::<[u8; 1024]>::cast::<u8>) {
15+
let mut _3: std::ptr::NonNull<u8>;
1516
scope 19 (inlined NonNull::<[u8; 1024]>::cast::<u8>) {
16-
let mut _3: *mut u8;
1717
scope 20 (inlined NonNull::<[u8; 1024]>::as_ptr) {
1818
}
1919
}
@@ -27,12 +27,10 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
2727
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
2828
scope 26 (inlined Layout::size) {
2929
}
30-
scope 27 (inlined NonNull::<u8>::as_ptr) {
31-
}
32-
scope 28 (inlined std::alloc::dealloc) {
33-
scope 29 (inlined Layout::size) {
30+
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
31+
scope 28 (inlined Layout::size) {
3432
}
35-
scope 30 (inlined Layout::alignment) {
33+
scope 29 (inlined Layout::alignment) {
3634
}
3735
}
3836
}
@@ -68,12 +66,14 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
6866
}
6967

7068
bb0: {
69+
StorageLive(_3);
7170
_2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>);
72-
_3 = copy _2 as *mut u8 (Transmute);
71+
_3 = copy _2 as std::ptr::NonNull<u8> (Transmute);
7372
_4 = alloc::alloc::__rust_dealloc(move _3, const 1024_usize, const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }}) -> [return: bb1, unwind unreachable];
7473
}
7574

7675
bb1: {
76+
StorageDead(_3);
7777
return;
7878
}
7979
}

tests/mir-opt/pre-codegen/drop_box_of_sized.drop_bytes.PreCodegen.after.panic-unwind.mir

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
1212
scope 17 (inlined Layout::size) {
1313
}
1414
scope 18 (inlined std::ptr::Unique::<[u8; 1024]>::cast::<u8>) {
15+
let mut _3: std::ptr::NonNull<u8>;
1516
scope 19 (inlined NonNull::<[u8; 1024]>::cast::<u8>) {
16-
let mut _3: *mut u8;
1717
scope 20 (inlined NonNull::<[u8; 1024]>::as_ptr) {
1818
}
1919
}
@@ -27,12 +27,10 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
2727
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
2828
scope 26 (inlined Layout::size) {
2929
}
30-
scope 27 (inlined NonNull::<u8>::as_ptr) {
31-
}
32-
scope 28 (inlined std::alloc::dealloc) {
33-
scope 29 (inlined Layout::size) {
30+
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
31+
scope 28 (inlined Layout::size) {
3432
}
35-
scope 30 (inlined Layout::alignment) {
33+
scope 29 (inlined Layout::alignment) {
3634
}
3735
}
3836
}
@@ -68,12 +66,14 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
6866
}
6967

7068
bb0: {
69+
StorageLive(_3);
7170
_2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>);
72-
_3 = copy _2 as *mut u8 (Transmute);
71+
_3 = copy _2 as std::ptr::NonNull<u8> (Transmute);
7372
_4 = alloc::alloc::__rust_dealloc(move _3, const 1024_usize, const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }}) -> [return: bb1, unwind unreachable];
7473
}
7574

7675
bb1: {
76+
StorageDead(_3);
7777
return;
7878
}
7979
}

tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-abort.mir

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ fn drop_generic(_1: *mut Box<T>) -> () {
1212
scope 17 (inlined Layout::size) {
1313
}
1414
scope 18 (inlined std::ptr::Unique::<T>::cast::<u8>) {
15+
let mut _4: std::ptr::NonNull<u8>;
1516
scope 19 (inlined NonNull::<T>::cast::<u8>) {
16-
let mut _4: *mut u8;
1717
scope 20 (inlined NonNull::<T>::as_ptr) {
1818
}
1919
}
@@ -27,12 +27,10 @@ fn drop_generic(_1: *mut Box<T>) -> () {
2727
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
2828
scope 26 (inlined Layout::size) {
2929
}
30-
scope 27 (inlined NonNull::<u8>::as_ptr) {
31-
}
32-
scope 28 (inlined std::alloc::dealloc) {
33-
scope 29 (inlined Layout::size) {
30+
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
31+
scope 28 (inlined Layout::size) {
3432
}
35-
scope 30 (inlined Layout::alignment) {
33+
scope 29 (inlined Layout::alignment) {
3634
}
3735
}
3836
}
@@ -69,13 +67,14 @@ fn drop_generic(_1: *mut Box<T>) -> () {
6967
}
7068

7169
bb0: {
70+
StorageLive(_4);
7271
_2 = copy (((*_1).0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>);
7372
_3 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
7473
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb1];
7574
}
7675

7776
bb1: {
78-
_4 = copy _2 as *mut u8 (Transmute);
77+
_4 = copy _2 as std::ptr::NonNull<u8> (Transmute);
7978
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb2];
8079
}
8180

@@ -84,6 +83,7 @@ fn drop_generic(_1: *mut Box<T>) -> () {
8483
}
8584

8685
bb3: {
86+
StorageDead(_4);
8787
return;
8888
}
8989
}

tests/mir-opt/pre-codegen/drop_box_of_sized.drop_generic.PreCodegen.after.panic-unwind.mir

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ fn drop_generic(_1: *mut Box<T>) -> () {
1212
scope 17 (inlined Layout::size) {
1313
}
1414
scope 18 (inlined std::ptr::Unique::<T>::cast::<u8>) {
15+
let mut _4: std::ptr::NonNull<u8>;
1516
scope 19 (inlined NonNull::<T>::cast::<u8>) {
16-
let mut _4: *mut u8;
1717
scope 20 (inlined NonNull::<T>::as_ptr) {
1818
}
1919
}
@@ -27,12 +27,10 @@ fn drop_generic(_1: *mut Box<T>) -> () {
2727
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
2828
scope 26 (inlined Layout::size) {
2929
}
30-
scope 27 (inlined NonNull::<u8>::as_ptr) {
31-
}
32-
scope 28 (inlined std::alloc::dealloc) {
33-
scope 29 (inlined Layout::size) {
30+
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
31+
scope 28 (inlined Layout::size) {
3432
}
35-
scope 30 (inlined Layout::alignment) {
33+
scope 29 (inlined Layout::alignment) {
3634
}
3735
}
3836
}
@@ -69,13 +67,14 @@ fn drop_generic(_1: *mut Box<T>) -> () {
6967
}
7068

7169
bb0: {
70+
StorageLive(_4);
7271
_2 = copy (((*_1).0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>);
7372
_3 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
7473
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb1];
7574
}
7675

7776
bb1: {
78-
_4 = copy _2 as *mut u8 (Transmute);
77+
_4 = copy _2 as std::ptr::NonNull<u8> (Transmute);
7978
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb2];
8079
}
8180

@@ -84,6 +83,7 @@ fn drop_generic(_1: *mut Box<T>) -> () {
8483
}
8584

8685
bb3: {
86+
StorageDead(_4);
8787
return;
8888
}
8989
}

tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
88
let _2: std::ptr::NonNull<[T]>;
99
let mut _3: *mut [T];
1010
let mut _4: *const [T];
11-
let _10: ();
11+
let _9: ();
1212
scope 3 {
1313
scope 4 {
1414
scope 17 (inlined Layout::size) {
@@ -28,15 +28,12 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
2828
scope 23 (inlined <std::alloc::Global as Allocator>::deallocate) {
2929
scope 24 (inlined std::alloc::Global::deallocate_impl) {
3030
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
31-
let mut _9: *mut u8;
3231
scope 26 (inlined Layout::size) {
3332
}
34-
scope 27 (inlined NonNull::<u8>::as_ptr) {
35-
}
36-
scope 28 (inlined std::alloc::dealloc) {
37-
scope 29 (inlined Layout::size) {
33+
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
34+
scope 28 (inlined Layout::size) {
3835
}
39-
scope 30 (inlined Layout::alignment) {
36+
scope 29 (inlined Layout::alignment) {
4037
}
4138
}
4239
}
@@ -87,25 +84,18 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
8784
bb1: {
8885
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
8986
StorageDead(_4);
90-
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
87+
switchInt(copy _5) -> [0: bb3, otherwise: bb2];
9188
}
9289

9390
bb2: {
9491
StorageLive(_7);
9592
_7 = copy _3 as *mut u8 (PtrToPtr);
9693
_8 = copy _7 as std::ptr::NonNull<u8> (Transmute);
9794
StorageDead(_7);
98-
StorageLive(_9);
99-
_9 = copy _8 as *mut u8 (Transmute);
100-
_10 = alloc::alloc::__rust_dealloc(move _9, move _5, move _6) -> [return: bb3, unwind unreachable];
95+
_9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable];
10196
}
10297

10398
bb3: {
104-
StorageDead(_9);
105-
goto -> bb4;
106-
}
107-
108-
bb4: {
10999
StorageDead(_2);
110100
StorageDead(_8);
111101
StorageDead(_3);

tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
88
let _2: std::ptr::NonNull<[T]>;
99
let mut _3: *mut [T];
1010
let mut _4: *const [T];
11-
let _10: ();
11+
let _9: ();
1212
scope 3 {
1313
scope 4 {
1414
scope 17 (inlined Layout::size) {
@@ -28,15 +28,12 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
2828
scope 23 (inlined <std::alloc::Global as Allocator>::deallocate) {
2929
scope 24 (inlined std::alloc::Global::deallocate_impl) {
3030
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
31-
let mut _9: *mut u8;
3231
scope 26 (inlined Layout::size) {
3332
}
34-
scope 27 (inlined NonNull::<u8>::as_ptr) {
35-
}
36-
scope 28 (inlined std::alloc::dealloc) {
37-
scope 29 (inlined Layout::size) {
33+
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
34+
scope 28 (inlined Layout::size) {
3835
}
39-
scope 30 (inlined Layout::alignment) {
36+
scope 29 (inlined Layout::alignment) {
4037
}
4138
}
4239
}
@@ -87,25 +84,18 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
8784
bb1: {
8885
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
8986
StorageDead(_4);
90-
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
87+
switchInt(copy _5) -> [0: bb3, otherwise: bb2];
9188
}
9289

9390
bb2: {
9491
StorageLive(_7);
9592
_7 = copy _3 as *mut u8 (PtrToPtr);
9693
_8 = copy _7 as std::ptr::NonNull<u8> (Transmute);
9794
StorageDead(_7);
98-
StorageLive(_9);
99-
_9 = copy _8 as *mut u8 (Transmute);
100-
_10 = alloc::alloc::__rust_dealloc(move _9, move _5, move _6) -> [return: bb3, unwind unreachable];
95+
_9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable];
10196
}
10297

10398
bb3: {
104-
StorageDead(_9);
105-
goto -> bb4;
106-
}
107-
108-
bb4: {
10999
StorageDead(_2);
110100
StorageDead(_8);
111101
StorageDead(_3);

0 commit comments

Comments
 (0)