Update __rust_[rd]ealloc to take NonNull<u8> instead of *mut u8

Passing null to it is [already UB](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=8dcd25a549c11de72adc94a668277779) anyway.
This commit is contained in:
Scott McMurray
2026-02-28 23:04:31 -08:00
parent c2c6f74fd2
commit 2c6ec51564
9 changed files with 76 additions and 97 deletions
+24 -5
View File
@@ -22,11 +22,16 @@
#[rustc_deallocator]
#[rustc_nounwind]
#[rustc_std_internal_symbol]
fn __rust_dealloc(ptr: *mut u8, size: usize, align: Alignment);
fn __rust_dealloc(ptr: NonNull<u8>, size: usize, align: Alignment);
#[rustc_reallocator]
#[rustc_nounwind]
#[rustc_std_internal_symbol]
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: Alignment, new_size: usize) -> *mut u8;
fn __rust_realloc(
ptr: NonNull<u8>,
old_size: usize,
align: Alignment,
new_size: usize,
) -> *mut u8;
#[rustc_allocator_zeroed]
#[rustc_nounwind]
#[rustc_std_internal_symbol]
@@ -112,6 +117,13 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
unsafe { dealloc_nonnull(NonNull::new_unchecked(ptr), layout) }
}
/// Same as [`dealloc`] but when you already have a non-null pointer
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn dealloc_nonnull(ptr: NonNull<u8>, layout: Layout) {
unsafe { __rust_dealloc(ptr, layout.size(), layout.alignment()) }
}
@@ -132,6 +144,13 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
unsafe { realloc_nonnull(NonNull::new_unchecked(ptr), layout, new_size) }
}
/// Same as [`realloc`] but when you already have a non-null pointer
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn realloc_nonnull(ptr: NonNull<u8>, layout: Layout, new_size: usize) -> *mut u8 {
unsafe { __rust_realloc(ptr, layout.size(), layout.alignment(), new_size) }
}
@@ -206,7 +225,7 @@ fn deallocate_impl_runtime(ptr: NonNull<u8>, layout: Layout) {
// allocation than requested.
// * Other conditions must be upheld by the caller, as per `Allocator::deallocate()`'s
// safety documentation.
unsafe { dealloc(ptr.as_ptr(), layout) }
unsafe { dealloc_nonnull(ptr, layout) }
}
}
@@ -236,7 +255,7 @@ fn grow_impl_runtime(
// `realloc` probably checks for `new_size >= old_layout.size()` or something similar.
hint::assert_unchecked(new_size >= old_layout.size());
let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
let raw_ptr = realloc_nonnull(ptr, old_layout, new_size);
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
if zeroed {
raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
@@ -285,7 +304,7 @@ fn shrink_impl_runtime(
// `realloc` probably checks for `new_size <= old_layout.size()` or something similar.
hint::assert_unchecked(new_size <= old_layout.size());
let raw_ptr = realloc(ptr.as_ptr(), old_layout, new_size);
let raw_ptr = realloc_nonnull(ptr, old_layout, new_size);
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(NonNull::slice_from_raw_parts(ptr, new_size))
},
@@ -12,8 +12,8 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
scope 17 (inlined Layout::size) {
}
scope 18 (inlined std::ptr::Unique::<[u8; 1024]>::cast::<u8>) {
let mut _3: std::ptr::NonNull<u8>;
scope 19 (inlined NonNull::<[u8; 1024]>::cast::<u8>) {
let mut _3: *mut u8;
scope 20 (inlined NonNull::<[u8; 1024]>::as_ptr) {
}
}
@@ -27,12 +27,10 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -68,12 +66,14 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
}
bb0: {
StorageLive(_3);
_2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>);
_3 = copy _2 as *mut u8 (Transmute);
_3 = copy _2 as std::ptr::NonNull<u8> (Transmute);
_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];
}
bb1: {
StorageDead(_3);
return;
}
}
@@ -12,8 +12,8 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
scope 17 (inlined Layout::size) {
}
scope 18 (inlined std::ptr::Unique::<[u8; 1024]>::cast::<u8>) {
let mut _3: std::ptr::NonNull<u8>;
scope 19 (inlined NonNull::<[u8; 1024]>::cast::<u8>) {
let mut _3: *mut u8;
scope 20 (inlined NonNull::<[u8; 1024]>::as_ptr) {
}
}
@@ -27,12 +27,10 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -68,12 +66,14 @@ fn drop_bytes(_1: *mut Box<[u8; 1024]>) -> () {
}
bb0: {
StorageLive(_3);
_2 = copy (((*_1).0: std::ptr::Unique<[u8; 1024]>).0: std::ptr::NonNull<[u8; 1024]>);
_3 = copy _2 as *mut u8 (Transmute);
_3 = copy _2 as std::ptr::NonNull<u8> (Transmute);
_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];
}
bb1: {
StorageDead(_3);
return;
}
}
@@ -12,8 +12,8 @@ fn drop_generic(_1: *mut Box<T>) -> () {
scope 17 (inlined Layout::size) {
}
scope 18 (inlined std::ptr::Unique::<T>::cast::<u8>) {
let mut _4: std::ptr::NonNull<u8>;
scope 19 (inlined NonNull::<T>::cast::<u8>) {
let mut _4: *mut u8;
scope 20 (inlined NonNull::<T>::as_ptr) {
}
}
@@ -27,12 +27,10 @@ fn drop_generic(_1: *mut Box<T>) -> () {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -69,13 +67,14 @@ fn drop_generic(_1: *mut Box<T>) -> () {
}
bb0: {
StorageLive(_4);
_2 = copy (((*_1).0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>);
_3 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb1];
}
bb1: {
_4 = copy _2 as *mut u8 (Transmute);
_4 = copy _2 as std::ptr::NonNull<u8> (Transmute);
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb2];
}
@@ -84,6 +83,7 @@ fn drop_generic(_1: *mut Box<T>) -> () {
}
bb3: {
StorageDead(_4);
return;
}
}
@@ -12,8 +12,8 @@ fn drop_generic(_1: *mut Box<T>) -> () {
scope 17 (inlined Layout::size) {
}
scope 18 (inlined std::ptr::Unique::<T>::cast::<u8>) {
let mut _4: std::ptr::NonNull<u8>;
scope 19 (inlined NonNull::<T>::cast::<u8>) {
let mut _4: *mut u8;
scope 20 (inlined NonNull::<T>::as_ptr) {
}
}
@@ -27,12 +27,10 @@ fn drop_generic(_1: *mut Box<T>) -> () {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -69,13 +67,14 @@ fn drop_generic(_1: *mut Box<T>) -> () {
}
bb0: {
StorageLive(_4);
_2 = copy (((*_1).0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>);
_3 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb1];
}
bb1: {
_4 = copy _2 as *mut u8 (Transmute);
_4 = copy _2 as std::ptr::NonNull<u8> (Transmute);
switchInt(const <T as std::mem::SizedTypeProperties>::SIZE) -> [0: bb3, otherwise: bb2];
}
@@ -84,6 +83,7 @@ fn drop_generic(_1: *mut Box<T>) -> () {
}
bb3: {
StorageDead(_4);
return;
}
}
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
let _2: std::ptr::NonNull<[T]>;
let mut _3: *mut [T];
let mut _4: *const [T];
let _10: ();
let _9: ();
scope 3 {
scope 4 {
scope 17 (inlined Layout::size) {
@@ -28,15 +28,12 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 23 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 24 (inlined std::alloc::Global::deallocate_impl) {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
let mut _9: *mut u8;
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -87,7 +84,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
bb1: {
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
switchInt(copy _5) -> [0: bb3, otherwise: bb2];
}
bb2: {
@@ -95,17 +92,10 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
_7 = copy _3 as *mut u8 (PtrToPtr);
_8 = copy _7 as std::ptr::NonNull<u8> (Transmute);
StorageDead(_7);
StorageLive(_9);
_9 = copy _8 as *mut u8 (Transmute);
_10 = alloc::alloc::__rust_dealloc(move _9, move _5, move _6) -> [return: bb3, unwind unreachable];
_9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable];
}
bb3: {
StorageDead(_9);
goto -> bb4;
}
bb4: {
StorageDead(_2);
StorageDead(_8);
StorageDead(_3);
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
let _2: std::ptr::NonNull<[T]>;
let mut _3: *mut [T];
let mut _4: *const [T];
let _10: ();
let _9: ();
scope 3 {
scope 4 {
scope 17 (inlined Layout::size) {
@@ -28,15 +28,12 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 23 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 24 (inlined std::alloc::Global::deallocate_impl) {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
let mut _9: *mut u8;
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -87,7 +84,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
bb1: {
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
switchInt(copy _5) -> [0: bb3, otherwise: bb2];
}
bb2: {
@@ -95,17 +92,10 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
_7 = copy _3 as *mut u8 (PtrToPtr);
_8 = copy _7 as std::ptr::NonNull<u8> (Transmute);
StorageDead(_7);
StorageLive(_9);
_9 = copy _8 as *mut u8 (Transmute);
_10 = alloc::alloc::__rust_dealloc(move _9, move _5, move _6) -> [return: bb3, unwind unreachable];
_9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable];
}
bb3: {
StorageDead(_9);
goto -> bb4;
}
bb4: {
StorageDead(_2);
StorageDead(_8);
StorageDead(_3);
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
let _2: std::ptr::NonNull<[T]>;
let mut _3: *mut [T];
let mut _4: *const [T];
let _10: ();
let _9: ();
scope 3 {
scope 4 {
scope 17 (inlined Layout::size) {
@@ -28,15 +28,12 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 23 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 24 (inlined std::alloc::Global::deallocate_impl) {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
let mut _9: *mut u8;
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -87,7 +84,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
bb1: {
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
switchInt(copy _5) -> [0: bb3, otherwise: bb2];
}
bb2: {
@@ -95,17 +92,10 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
_7 = copy _3 as *mut u8 (PtrToPtr);
_8 = copy _7 as std::ptr::NonNull<u8> (Transmute);
StorageDead(_7);
StorageLive(_9);
_9 = copy _8 as *mut u8 (Transmute);
_10 = alloc::alloc::__rust_dealloc(move _9, move _5, move _6) -> [return: bb3, unwind unreachable];
_9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable];
}
bb3: {
StorageDead(_9);
goto -> bb4;
}
bb4: {
StorageDead(_2);
StorageDead(_8);
StorageDead(_3);
@@ -8,7 +8,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
let _2: std::ptr::NonNull<[T]>;
let mut _3: *mut [T];
let mut _4: *const [T];
let _10: ();
let _9: ();
scope 3 {
scope 4 {
scope 17 (inlined Layout::size) {
@@ -28,15 +28,12 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 23 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 24 (inlined std::alloc::Global::deallocate_impl) {
scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) {
let mut _9: *mut u8;
scope 26 (inlined Layout::size) {
}
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 28 (inlined std::alloc::dealloc) {
scope 29 (inlined Layout::size) {
scope 27 (inlined alloc::alloc::dealloc_nonnull) {
scope 28 (inlined Layout::size) {
}
scope 30 (inlined Layout::alignment) {
scope 29 (inlined Layout::alignment) {
}
}
}
@@ -87,7 +84,7 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
bb1: {
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN as std::ptr::Alignment (Transmute);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
switchInt(copy _5) -> [0: bb3, otherwise: bb2];
}
bb2: {
@@ -95,17 +92,10 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
_7 = copy _3 as *mut u8 (PtrToPtr);
_8 = copy _7 as std::ptr::NonNull<u8> (Transmute);
StorageDead(_7);
StorageLive(_9);
_9 = copy _8 as *mut u8 (Transmute);
_10 = alloc::alloc::__rust_dealloc(move _9, move _5, move _6) -> [return: bb3, unwind unreachable];
_9 = alloc::alloc::__rust_dealloc(move _8, move _5, move _6) -> [return: bb3, unwind unreachable];
}
bb3: {
StorageDead(_9);
goto -> bb4;
}
bb4: {
StorageDead(_2);
StorageDead(_8);
StorageDead(_3);