From d872845eae7f9988995fb8ca35f86d08de999409 Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Wed, 26 Mar 2025 20:45:55 +0000 Subject: [PATCH 1/3] Expose `Unique::from` in const internally --- library/core/src/ptr/unique.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 4810ebe01f9bb..d688ce2a07a6a 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -100,6 +100,12 @@ impl Unique { } } + /// Create a new `Unique` from a `NonNull` in const context. + #[inline] + pub const fn from_non_null(pointer: NonNull) -> Self { + Unique { pointer, _marker: PhantomData } + } + /// Acquires the underlying `*mut` pointer. #[must_use = "`self` will be dropped if the result is not used"] #[inline] @@ -202,6 +208,6 @@ impl From> for Unique { /// This conversion is infallible since `NonNull` cannot be null. #[inline] fn from(pointer: NonNull) -> Self { - Unique { pointer, _marker: PhantomData } + Unique::from_non_null(pointer) } } From 78e962139020df03174f03da6af91acc5cbb37e3 Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Tue, 25 Mar 2025 21:43:19 +0000 Subject: [PATCH 2/3] Pass `Alignment` for `RawVecInner::new_in` Encodes the safety constraint that `Unique`'s pointer must be non-zero into the API. --- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec/mod.rs | 9 +++++---- library/alloctests/lib.rs | 1 + library/core/src/alloc/layout.rs | 8 ++++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f0cdb1e4e0f78..04858667230b3 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -135,6 +135,7 @@ #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] #![feature(pointer_like_trait)] +#![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 99ebc5c4bfca8..83facd9d93216 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -6,7 +6,7 @@ use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; -use core::ptr::{self, NonNull, Unique}; +use core::ptr::{self, Alignment, NonNull, Unique}; use core::{cmp, hint}; #[cfg(not(no_global_oom_handling))] @@ -177,7 +177,7 @@ impl RawVec { /// the returned `RawVec`. #[inline] pub(crate) const fn new_in(alloc: A) -> Self { - Self { inner: RawVecInner::new_in(alloc, align_of::()), _marker: PhantomData } + Self { inner: RawVecInner::new_in(alloc, Alignment::of::()), _marker: PhantomData } } /// Like `with_capacity`, but parameterized over the choice of @@ -409,7 +409,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] - const fn new_in(alloc: A, align: usize) -> Self { + const fn new_in(alloc: A, align: Alignment) -> Self { + // SAFETY: `Alignment` is non-zero. let ptr = unsafe { core::mem::transmute(align) }; // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr, cap: ZERO_CAP, alloc } @@ -465,7 +466,7 @@ impl RawVecInner { // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. if layout.size() == 0 { - return Ok(Self::new_in(alloc, elem_layout.align())); + return Ok(Self::new_in(alloc, elem_layout.alignment())); } if let Err(err) = alloc_guard(layout.size()) { diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 6ce8a6d9ca174..3241b4b00454b 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -28,6 +28,7 @@ #![feature(iter_next_chunk)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(sized_type_properties)] #![feature(slice_iter_mut_as_mut_slice)] diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 1595a3af883d1..e8a03aadc3390 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -520,6 +520,14 @@ impl Layout { unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) } } } + + /// Perma-unstable access to `align` as `Alignment` type. + #[unstable(issue = "none", feature = "std_internals")] + #[doc(hidden)] + #[inline] + pub const fn alignment(&self) -> Alignment { + self.align + } } #[stable(feature = "alloc_layout", since = "1.28.0")] From aadfd810f62e2e07440672cc20a0540c9904d69b Mon Sep 17 00:00:00 2001 From: James Wainwright Date: Tue, 25 Mar 2025 21:44:54 +0000 Subject: [PATCH 3/3] Swap usize -> ptr transmute for strict_pov API Removes some unsafety and reduces the number of `usize` -> `ptr` transmutes which might be helpful for CHERI-like targets in the future. --- library/alloc/src/raw_vec/mod.rs | 3 +-- library/alloctests/lib.rs | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 83facd9d93216..a989e5b55b3d1 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -410,8 +410,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] const fn new_in(alloc: A, align: Alignment) -> Self { - // SAFETY: `Alignment` is non-zero. - let ptr = unsafe { core::mem::transmute(align) }; + let ptr = Unique::from_non_null(NonNull::without_provenance(align.as_nonzero())); // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr, cap: ZERO_CAP, alloc } } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 3241b4b00454b..56e60ed4c8448 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -28,6 +28,7 @@ #![feature(iter_next_chunk)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(nonnull_provenance)] #![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(sized_type_properties)]