Auto merge of #138951 - jwnrt:alloc-raw-vec-strict-prov, r=Noratrieb
Replace last `usize` -> `ptr` transmute in `alloc` with strict provenance API This replaces the `usize -> ptr` transmute in `RawVecInner::new_in` with a strict provenance API (`NonNull::without_provenance`). The API is changed to take an `Alignment` which encodes the non-null constraint needed for `Unique` and allows us to do the construction safely. Two internal-only APIs were added to let us avoid UB-checking in this hot code: `Layout::alignment` to get the `Alignment` type directly rather than as a `usize`, and `Unique::from_non_null` to create `Unique` in const context without a transmute.
This commit is contained in:
commit
25a615bf82
5 changed files with 23 additions and 6 deletions
|
@ -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)]
|
||||
|
|
|
@ -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<T, A: Allocator> RawVec<T, A> {
|
|||
/// the returned `RawVec`.
|
||||
#[inline]
|
||||
pub(crate) const fn new_in(alloc: A) -> Self {
|
||||
Self { inner: RawVecInner::new_in(alloc, align_of::<T>()), _marker: PhantomData }
|
||||
Self { inner: RawVecInner::new_in(alloc, Alignment::of::<T>()), _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Like `with_capacity`, but parameterized over the choice of
|
||||
|
@ -409,8 +409,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
|
|||
|
||||
impl<A: Allocator> RawVecInner<A> {
|
||||
#[inline]
|
||||
const fn new_in(alloc: A, align: usize) -> Self {
|
||||
let ptr = unsafe { core::mem::transmute(align) };
|
||||
const fn new_in(alloc: A, align: Alignment) -> Self {
|
||||
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 }
|
||||
}
|
||||
|
@ -465,7 +465,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
|
||||
// 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()) {
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#![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)]
|
||||
#![feature(slice_iter_mut_as_mut_slice)]
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -100,6 +100,12 @@ impl<T: ?Sized> Unique<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new `Unique` from a `NonNull` in const context.
|
||||
#[inline]
|
||||
pub const fn from_non_null(pointer: NonNull<T>) -> 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<T: ?Sized> From<NonNull<T>> for Unique<T> {
|
|||
/// This conversion is infallible since `NonNull` cannot be null.
|
||||
#[inline]
|
||||
fn from(pointer: NonNull<T>) -> Self {
|
||||
Unique { pointer, _marker: PhantomData }
|
||||
Unique::from_non_null(pointer)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue