Rollup merge of #148769 - stabilize/alloc_layout_extra, r=scottmcm
Stabilize `alloc_layout_extra` Tracking issue: rust-lang/rust#55724 FCP completed in https://github.com/rust-lang/rust/issues/55724#issuecomment-3447699364 Closes rust-lang/rust#55724 ---- As per https://github.com/rust-lang/rust/issues/55724#issuecomment-3403555985, - `repeat_packed` and `extend_packed` are unchanged - `repeat` now excludes trailing padding on the last element from the total array size - `dangling` renamed to `dangling_ptr` - `padding_needed_for` not stabilized, changed to accept `Alignment` instead of `usize` and moved to the `ptr_aligment_type` feature flag (tracking issue: rust-lang/rust#102070)
This commit is contained in:
commit
99b29620ca
15 changed files with 58 additions and 51 deletions
|
|
@ -14,11 +14,10 @@ diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs
|
|||
index 1e336bf..35e6f54 100644
|
||||
--- a/coretests/tests/lib.rs
|
||||
+++ b/coretests/tests/lib.rs
|
||||
@@ -2,5 +2,4 @@
|
||||
@@ -2,4 +2,3 @@
|
||||
// tidy-alphabetical-start
|
||||
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_select))]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(array_ptr_get)]
|
||||
diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs
|
||||
index b735957..ea728b6 100644
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ impl Global {
|
|||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
fn alloc_impl_runtime(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
|
||||
match layout.size() {
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
|
||||
// SAFETY: `layout` is non-zero in size,
|
||||
size => unsafe {
|
||||
let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) };
|
||||
|
|
@ -277,7 +277,7 @@ impl Global {
|
|||
// SAFETY: conditions must be upheld by the caller
|
||||
0 => unsafe {
|
||||
self.deallocate(ptr, old_layout);
|
||||
Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
|
||||
Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0))
|
||||
},
|
||||
|
||||
// SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
|
||||
|
|
@ -368,7 +368,7 @@ impl Global {
|
|||
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
|
||||
const fn alloc_impl_const(layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
|
||||
match layout.size() {
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
|
||||
// SAFETY: `layout` is non-zero in size,
|
||||
size => unsafe {
|
||||
let raw_ptr = core::intrinsics::const_allocate(layout.size(), layout.align());
|
||||
|
|
|
|||
|
|
@ -834,7 +834,7 @@ impl<T: ?Sized + CloneToUninit, A: Allocator> Box<T, A> {
|
|||
}
|
||||
let layout = Layout::for_value::<T>(src);
|
||||
let (ptr, guard) = if layout.size() == 0 {
|
||||
(layout.dangling(), None)
|
||||
(layout.dangling_ptr(), None)
|
||||
} else {
|
||||
// Safety: layout is non-zero-sized
|
||||
let ptr = alloc.allocate(layout)?.cast();
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ impl<H> WithHeader<H> {
|
|||
// Some paranoia checking, mostly so that the ThinBox tests are
|
||||
// more able to catch issues.
|
||||
debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);
|
||||
layout.dangling()
|
||||
layout.dangling_ptr()
|
||||
} else {
|
||||
let ptr = alloc::alloc(layout);
|
||||
if ptr.is_null() {
|
||||
|
|
@ -282,7 +282,7 @@ impl<H> WithHeader<H> {
|
|||
// Some paranoia checking, mostly so that the ThinBox tests are
|
||||
// more able to catch issues.
|
||||
debug_assert!(value_offset == 0 && size_of::<T>() == 0 && size_of::<H>() == 0);
|
||||
layout.dangling()
|
||||
layout.dangling_ptr()
|
||||
} else {
|
||||
let ptr = alloc::alloc(layout);
|
||||
if ptr.is_null() {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@
|
|||
// Library features:
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(not(no_global_oom_handling), feature(string_replace_in_place))]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(array_into_iter_constructors)]
|
||||
#![feature(ascii_char)]
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ use core::panic::{RefUnwindSafe, UnwindSafe};
|
|||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::pin::Pin;
|
||||
use core::pin::PinCoerceUnsized;
|
||||
use core::ptr::{self, NonNull, drop_in_place};
|
||||
use core::ptr::{self, Alignment, NonNull, drop_in_place};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::slice::from_raw_parts_mut;
|
||||
use core::{borrow, fmt, hint};
|
||||
|
|
@ -3847,11 +3847,11 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
|
|||
// and extern types, the input safety requirement is currently enough to
|
||||
// satisfy the requirements of align_of_val_raw; this is an implementation
|
||||
// detail of the language that must not be relied upon outside of std.
|
||||
unsafe { data_offset_align(align_of_val_raw(ptr)) }
|
||||
unsafe { data_offset_align(Alignment::new_unchecked(align_of_val_raw(ptr))) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn data_offset_align(align: usize) -> usize {
|
||||
fn data_offset_align(align: Alignment) -> usize {
|
||||
let layout = Layout::new::<RcInner<()>>();
|
||||
layout.size() + layout.padding_needed_for(align)
|
||||
}
|
||||
|
|
@ -4478,7 +4478,7 @@ impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
|
|||
|
||||
/// Returns the pointer to be written into to initialize the [`Rc`].
|
||||
fn data_ptr(&mut self) -> *mut T {
|
||||
let offset = data_offset_align(self.layout_for_value.align());
|
||||
let offset = data_offset_align(self.layout_for_value.alignment());
|
||||
unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Lega
|
|||
use core::ops::{Residual, Try};
|
||||
use core::panic::{RefUnwindSafe, UnwindSafe};
|
||||
use core::pin::{Pin, PinCoerceUnsized};
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::ptr::{self, Alignment, NonNull};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::slice::from_raw_parts_mut;
|
||||
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
|
||||
|
|
@ -4208,11 +4208,11 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
|
|||
// and extern types, the input safety requirement is currently enough to
|
||||
// satisfy the requirements of align_of_val_raw; this is an implementation
|
||||
// detail of the language that must not be relied upon outside of std.
|
||||
unsafe { data_offset_align(align_of_val_raw(ptr)) }
|
||||
unsafe { data_offset_align(Alignment::new_unchecked(align_of_val_raw(ptr))) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn data_offset_align(align: usize) -> usize {
|
||||
fn data_offset_align(align: Alignment) -> usize {
|
||||
let layout = Layout::new::<ArcInner<()>>();
|
||||
layout.size() + layout.padding_needed_for(align)
|
||||
}
|
||||
|
|
@ -4258,7 +4258,7 @@ impl<T: ?Sized, A: Allocator> UniqueArcUninit<T, A> {
|
|||
|
||||
/// Returns the pointer to be written into to initialize the [`Arc`].
|
||||
fn data_ptr(&mut self) -> *mut T {
|
||||
let offset = data_offset_align(self.layout_for_value.align());
|
||||
let offset = data_offset_align(self.layout_for_value.alignment());
|
||||
unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
//
|
||||
// Library features:
|
||||
// tidy-alphabetical-start
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(array_into_iter_constructors)]
|
||||
#![feature(assert_matches)]
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ pub struct ConstAllocator;
|
|||
unsafe impl Allocator for ConstAllocator {
|
||||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
match layout.size() {
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
|
||||
_ => unsafe {
|
||||
let ptr = core::intrinsics::const_allocate(layout.size(), layout.align());
|
||||
Ok(NonNull::new_unchecked(ptr as *mut [u8; 0] as *mut [u8]))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(allocator_api)]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(const_heap)]
|
||||
#![feature(deque_extend_front)]
|
||||
#![feature(iter_array_chunks)]
|
||||
|
|
|
|||
|
|
@ -217,10 +217,11 @@ impl Layout {
|
|||
/// be that of a valid pointer, which means this must not be used
|
||||
/// as a "not yet initialized" sentinel value.
|
||||
/// Types that lazily allocate must track initialization by some other means.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn dangling(&self) -> NonNull<u8> {
|
||||
pub const fn dangling_ptr(&self) -> NonNull<u8> {
|
||||
NonNull::without_provenance(self.align.as_nonzero())
|
||||
}
|
||||
|
||||
|
|
@ -250,29 +251,23 @@ impl Layout {
|
|||
}
|
||||
|
||||
/// Returns the amount of padding we must insert after `self`
|
||||
/// to ensure that the following address will satisfy `align`
|
||||
/// (measured in bytes).
|
||||
/// to ensure that the following address will satisfy `alignment`.
|
||||
///
|
||||
/// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)`
|
||||
/// e.g., if `self.size()` is 9, then `self.padding_needed_for(alignment4)`
|
||||
/// (where `alignment4.as_usize() == 4`)
|
||||
/// returns 3, because that is the minimum number of bytes of
|
||||
/// padding required to get a 4-aligned address (assuming that the
|
||||
/// corresponding memory block starts at a 4-aligned address).
|
||||
///
|
||||
/// The return value of this function has no meaning if `align` is
|
||||
/// not a power-of-two.
|
||||
///
|
||||
/// Note that the utility of the returned value requires `align`
|
||||
/// Note that the utility of the returned value requires `alignment`
|
||||
/// to be less than or equal to the alignment of the starting
|
||||
/// address for the whole allocated block of memory. One way to
|
||||
/// satisfy this constraint is to ensure `align <= self.align()`.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[must_use = "this returns the padding needed, \
|
||||
without modifying the `Layout`"]
|
||||
/// satisfy this constraint is to ensure `alignment.as_usize() <= self.align()`.
|
||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||
#[must_use = "this returns the padding needed, without modifying the `Layout`"]
|
||||
#[inline]
|
||||
pub const fn padding_needed_for(&self, align: usize) -> usize {
|
||||
// FIXME: Can we just change the type on this to `Alignment`?
|
||||
let Some(align) = Alignment::new(align) else { return usize::MAX };
|
||||
let len_rounded_up = self.size_rounded_up_to_custom_align(align);
|
||||
pub const fn padding_needed_for(&self, alignment: Alignment) -> usize {
|
||||
let len_rounded_up = self.size_rounded_up_to_custom_align(alignment);
|
||||
// SAFETY: Cannot overflow because the rounded-up value is never less
|
||||
unsafe { unchecked_sub(len_rounded_up, self.size) }
|
||||
}
|
||||
|
|
@ -335,6 +330,8 @@ impl Layout {
|
|||
/// layout of the array and `offs` is the distance between the start
|
||||
/// of each element in the array.
|
||||
///
|
||||
/// Does not include padding after the trailing element.
|
||||
///
|
||||
/// (That distance between elements is sometimes known as "stride".)
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutError`.
|
||||
|
|
@ -342,7 +339,6 @@ impl Layout {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(alloc_layout_extra)]
|
||||
/// use std::alloc::Layout;
|
||||
///
|
||||
/// // All rust types have a size that's a multiple of their alignment.
|
||||
|
|
@ -353,17 +349,32 @@ impl Layout {
|
|||
/// // But you can manually make layouts which don't meet that rule.
|
||||
/// let padding_needed = Layout::from_size_align(6, 4).unwrap();
|
||||
/// let repeated = padding_needed.repeat(3).unwrap();
|
||||
/// assert_eq!(repeated, (Layout::from_size_align(24, 4).unwrap(), 8));
|
||||
/// assert_eq!(repeated, (Layout::from_size_align(22, 4).unwrap(), 8));
|
||||
///
|
||||
/// // Repeating an element zero times has zero size, but keeps the alignment (like `[T; 0]`)
|
||||
/// let repeated = normal.repeat(0).unwrap();
|
||||
/// assert_eq!(repeated, (Layout::from_size_align(0, 4).unwrap(), 12));
|
||||
/// let repeated = padding_needed.repeat(0).unwrap();
|
||||
/// assert_eq!(repeated, (Layout::from_size_align(0, 4).unwrap(), 8));
|
||||
/// ```
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> {
|
||||
// FIXME(const-hack): the following could be way shorter with `?`
|
||||
let padded = self.pad_to_align();
|
||||
if let Ok(repeated) = padded.repeat_packed(n) {
|
||||
Ok((repeated, padded.size()))
|
||||
let Ok(result) = (if let Some(k) = n.checked_sub(1) {
|
||||
let Ok(repeated) = padded.repeat_packed(k) else {
|
||||
return Err(LayoutError);
|
||||
};
|
||||
repeated.extend_packed(*self)
|
||||
} else {
|
||||
Err(LayoutError)
|
||||
}
|
||||
debug_assert!(n == 0);
|
||||
self.repeat_packed(0)
|
||||
}) else {
|
||||
return Err(LayoutError);
|
||||
};
|
||||
Ok((result, padded.size()))
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `self` followed by
|
||||
|
|
@ -443,7 +454,8 @@ impl Layout {
|
|||
/// aligned.
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutError`.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
pub const fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> {
|
||||
if let Some(size) = self.size.checked_mul(n) {
|
||||
|
|
@ -460,7 +472,8 @@ impl Layout {
|
|||
/// and is not incorporated *at all* into the resulting layout.
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutError`.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
pub const fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
|
||||
// SAFETY: each `size` is at most `isize::MAX == usize::MAX/2`, so the
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ fn const_unchecked_layout() {
|
|||
const SIZE: usize = 0x2000;
|
||||
const ALIGN: usize = 0x1000;
|
||||
const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(SIZE, ALIGN) };
|
||||
const DANGLING: NonNull<u8> = LAYOUT.dangling();
|
||||
const DANGLING: NonNull<u8> = LAYOUT.dangling_ptr();
|
||||
assert_eq!(LAYOUT.size(), SIZE);
|
||||
assert_eq!(LAYOUT.align(), ALIGN);
|
||||
assert_eq!(Some(DANGLING), NonNull::new(ptr::without_provenance_mut(ALIGN)));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_select))]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(array_ptr_get)]
|
||||
#![feature(array_try_from_fn)]
|
||||
#![feature(array_try_map)]
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ impl System {
|
|||
#[inline]
|
||||
fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result<NonNull<[u8]>, AllocError> {
|
||||
match layout.size() {
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)),
|
||||
0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)),
|
||||
// SAFETY: `layout` is non-zero in size,
|
||||
size => unsafe {
|
||||
let raw_ptr = if zeroed {
|
||||
|
|
@ -266,7 +266,7 @@ unsafe impl Allocator for System {
|
|||
// SAFETY: conditions must be upheld by the caller
|
||||
0 => unsafe {
|
||||
Allocator::deallocate(self, ptr, old_layout);
|
||||
Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
|
||||
Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0))
|
||||
},
|
||||
|
||||
// SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller
|
||||
|
|
|
|||
|
|
@ -367,7 +367,6 @@
|
|||
//
|
||||
// Library features (alloc):
|
||||
// tidy-alphabetical-start
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(clone_from_ref)]
|
||||
#![feature(get_mut_unchecked)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue