Skip to content

Commit 25a615b

Browse files
committed
Auto merge of rust-lang#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.
2 parents 2fa8b11 + aadfd81 commit 25a615b

File tree

5 files changed

+23
-6
lines changed

5 files changed

+23
-6
lines changed

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
#![feature(pattern)]
136136
#![feature(pin_coerce_unsized_trait)]
137137
#![feature(pointer_like_trait)]
138+
#![feature(ptr_alignment_type)]
138139
#![feature(ptr_internals)]
139140
#![feature(ptr_metadata)]
140141
#![feature(set_ptr_value)]

library/alloc/src/raw_vec/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use core::marker::PhantomData;
88
use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
9-
use core::ptr::{self, NonNull, Unique};
9+
use core::ptr::{self, Alignment, NonNull, Unique};
1010
use core::{cmp, hint};
1111

1212
#[cfg(not(no_global_oom_handling))]
@@ -177,7 +177,7 @@ impl<T, A: Allocator> RawVec<T, A> {
177177
/// the returned `RawVec`.
178178
#[inline]
179179
pub(crate) const fn new_in(alloc: A) -> Self {
180-
Self { inner: RawVecInner::new_in(alloc, align_of::<T>()), _marker: PhantomData }
180+
Self { inner: RawVecInner::new_in(alloc, Alignment::of::<T>()), _marker: PhantomData }
181181
}
182182

183183
/// 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> {
409409

410410
impl<A: Allocator> RawVecInner<A> {
411411
#[inline]
412-
const fn new_in(alloc: A, align: usize) -> Self {
413-
let ptr = unsafe { core::mem::transmute(align) };
412+
const fn new_in(alloc: A, align: Alignment) -> Self {
413+
let ptr = Unique::from_non_null(NonNull::without_provenance(align.as_nonzero()));
414414
// `cap: 0` means "unallocated". zero-sized types are ignored.
415415
Self { ptr, cap: ZERO_CAP, alloc }
416416
}
@@ -465,7 +465,7 @@ impl<A: Allocator> RawVecInner<A> {
465465

466466
// Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
467467
if layout.size() == 0 {
468-
return Ok(Self::new_in(alloc, elem_layout.align()));
468+
return Ok(Self::new_in(alloc, elem_layout.alignment()));
469469
}
470470

471471
if let Err(err) = alloc_guard(layout.size()) {

library/alloctests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#![feature(iter_next_chunk)]
2929
#![feature(maybe_uninit_slice)]
3030
#![feature(maybe_uninit_uninit_array_transpose)]
31+
#![feature(nonnull_provenance)]
32+
#![feature(ptr_alignment_type)]
3133
#![feature(ptr_internals)]
3234
#![feature(sized_type_properties)]
3335
#![feature(slice_iter_mut_as_mut_slice)]

library/core/src/alloc/layout.rs

+8
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,14 @@ impl Layout {
520520
unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) }
521521
}
522522
}
523+
524+
/// Perma-unstable access to `align` as `Alignment` type.
525+
#[unstable(issue = "none", feature = "std_internals")]
526+
#[doc(hidden)]
527+
#[inline]
528+
pub const fn alignment(&self) -> Alignment {
529+
self.align
530+
}
523531
}
524532

525533
#[stable(feature = "alloc_layout", since = "1.28.0")]

library/core/src/ptr/unique.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ impl<T: ?Sized> Unique<T> {
100100
}
101101
}
102102

103+
/// Create a new `Unique` from a `NonNull` in const context.
104+
#[inline]
105+
pub const fn from_non_null(pointer: NonNull<T>) -> Self {
106+
Unique { pointer, _marker: PhantomData }
107+
}
108+
103109
/// Acquires the underlying `*mut` pointer.
104110
#[must_use = "`self` will be dropped if the result is not used"]
105111
#[inline]
@@ -202,6 +208,6 @@ impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
202208
/// This conversion is infallible since `NonNull` cannot be null.
203209
#[inline]
204210
fn from(pointer: NonNull<T>) -> Self {
205-
Unique { pointer, _marker: PhantomData }
211+
Unique::from_non_null(pointer)
206212
}
207213
}

0 commit comments

Comments
 (0)