ptr_aligment_type: add more APIs

This commit is contained in:
Pavel Grigorenko 2025-11-09 20:48:55 +03:00
parent fffc4fcf96
commit bc0cce1595
11 changed files with 330 additions and 153 deletions

View file

@ -252,7 +252,7 @@ use core::intrinsics::abort;
#[cfg(not(no_global_oom_handling))]
use core::iter;
use core::marker::{PhantomData, Unsize};
use core::mem::{self, ManuallyDrop, align_of_val_raw};
use core::mem::{self, ManuallyDrop};
use core::num::NonZeroUsize;
use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
#[cfg(not(no_global_oom_handling))]
@ -3845,15 +3845,15 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
// Because RcInner is repr(C), it will always be the last field in memory.
// SAFETY: since the only unsized types possible are slices, trait objects,
// and extern types, the input safety requirement is currently enough to
// satisfy the requirements of align_of_val_raw; this is an implementation
// satisfy the requirements of Alignment::of_val_raw; this is an implementation
// detail of the language that must not be relied upon outside of std.
unsafe { data_offset_align(Alignment::new_unchecked(align_of_val_raw(ptr))) }
unsafe { data_offset_alignment(Alignment::of_val_raw(ptr)) }
}
#[inline]
fn data_offset_align(align: Alignment) -> usize {
fn data_offset_alignment(alignment: Alignment) -> usize {
let layout = Layout::new::<RcInner<()>>();
layout.size() + layout.padding_needed_for(align)
layout.size() + layout.padding_needed_for(alignment)
}
/// A uniquely owned [`Rc`].
@ -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.alignment());
let offset = data_offset_alignment(self.layout_for_value.alignment());
unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T }
}

View file

@ -19,7 +19,7 @@ use core::intrinsics::abort;
#[cfg(not(no_global_oom_handling))]
use core::iter;
use core::marker::{PhantomData, Unsize};
use core::mem::{self, ManuallyDrop, align_of_val_raw};
use core::mem::{self, ManuallyDrop};
use core::num::NonZeroUsize;
use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
#[cfg(not(no_global_oom_handling))]
@ -4206,15 +4206,15 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
// Because ArcInner is repr(C), it will always be the last field in memory.
// SAFETY: since the only unsized types possible are slices, trait objects,
// and extern types, the input safety requirement is currently enough to
// satisfy the requirements of align_of_val_raw; this is an implementation
// satisfy the requirements of Alignment::of_val_raw; this is an implementation
// detail of the language that must not be relied upon outside of std.
unsafe { data_offset_align(Alignment::new_unchecked(align_of_val_raw(ptr))) }
unsafe { data_offset_alignment(Alignment::of_val_raw(ptr)) }
}
#[inline]
fn data_offset_align(align: Alignment) -> usize {
fn data_offset_alignment(alignment: Alignment) -> usize {
let layout = Layout::new::<ArcInner<()>>();
layout.size() + layout.padding_needed_for(align)
layout.size() + layout.padding_needed_for(alignment)
}
/// A unique owning pointer to an [`ArcInner`] **that does not imply the contents are initialized,**
@ -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.alignment());
let offset = data_offset_alignment(self.layout_for_value.alignment());
unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T }
}

View file

@ -67,15 +67,16 @@ impl Layout {
#[inline]
const fn is_size_align_valid(size: usize, align: usize) -> bool {
let Some(align) = Alignment::new(align) else { return false };
if size > Self::max_size_for_align(align) {
return false;
}
true
let Some(alignment) = Alignment::new(align) else { return false };
Self::is_size_alignment_valid(size, alignment)
}
const fn is_size_alignment_valid(size: usize, alignment: Alignment) -> bool {
size <= Self::max_size_for_alignment(alignment)
}
#[inline(always)]
const fn max_size_for_align(align: Alignment) -> usize {
const fn max_size_for_alignment(alignment: Alignment) -> usize {
// (power-of-two implies align != 0.)
// Rounded up size is:
@ -93,18 +94,28 @@ impl Layout {
// SAFETY: the maximum possible alignment is `isize::MAX + 1`,
// so the subtraction cannot overflow.
unsafe { unchecked_sub(isize::MAX as usize + 1, align.as_usize()) }
unsafe { unchecked_sub(isize::MAX as usize + 1, alignment.as_usize()) }
}
/// Internal helper constructor to skip revalidating alignment validity.
/// Constructs a `Layout` from a given `size` and `alignment`,
/// or returns `LayoutError` if any of the following conditions
/// are not met:
///
/// * `size`, when rounded up to the nearest multiple of `alignment`,
/// must not overflow `isize` (i.e., the rounded value must be
/// less than or equal to `isize::MAX`).
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
const fn from_size_alignment(size: usize, align: Alignment) -> Result<Self, LayoutError> {
if size > Self::max_size_for_align(align) {
return Err(LayoutError);
pub const fn from_size_alignment(
size: usize,
alignment: Alignment,
) -> Result<Self, LayoutError> {
if Layout::is_size_alignment_valid(size, alignment) {
// SAFETY: Layout::size invariants checked above.
Ok(Layout { size, align: alignment })
} else {
Err(LayoutError)
}
// SAFETY: Layout::size invariants checked above.
Ok(Layout { size, align })
}
/// Creates a layout, bypassing all checks.
@ -132,6 +143,30 @@ impl Layout {
unsafe { Layout { size, align: mem::transmute(align) } }
}
/// Creates a layout, bypassing all checks.
///
/// # Safety
///
/// This function is unsafe as it does not verify the preconditions from
/// [`Layout::from_size_alignment`].
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[must_use]
#[inline]
#[track_caller]
pub const unsafe fn from_size_alignment_unchecked(size: usize, alignment: Alignment) -> Self {
assert_unsafe_precondition!(
check_library_ub,
"Layout::from_size_alignment_unchecked requires \
that the rounded-up allocation size does not exceed isize::MAX",
(
size: usize = size,
alignment: Alignment = alignment,
) => Layout::is_size_alignment_valid(size, alignment)
);
// SAFETY: the caller is required to uphold the preconditions.
Layout { size, align: alignment }
}
/// The minimum size in bytes for a memory block of this layout.
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
@ -153,6 +188,16 @@ impl Layout {
self.align.as_usize()
}
/// The minimum byte alignment for a memory block of this layout.
///
/// The returned alignment is guaranteed to be a power of two.
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[must_use = "this returns the minimum alignment, without modifying the layout"]
#[inline]
pub const fn alignment(&self) -> Alignment {
self.align
}
/// Constructs a `Layout` suitable for holding a value of type `T`.
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
@ -170,9 +215,9 @@ impl Layout {
#[must_use]
#[inline]
pub const fn for_value<T: ?Sized>(t: &T) -> Self {
let (size, align) = (size_of_val(t), align_of_val(t));
let (size, alignment) = (size_of_val(t), Alignment::of_val(t));
// SAFETY: see rationale in `new` for why this is using the unsafe variant
unsafe { Layout::from_size_align_unchecked(size, align) }
unsafe { Layout::from_size_alignment_unchecked(size, alignment) }
}
/// Produces layout describing a record that could be used to
@ -204,11 +249,12 @@ impl Layout {
/// [extern type]: ../../unstable-book/language-features/extern-types.html
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[must_use]
#[inline]
pub const unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
// SAFETY: we pass along the prerequisites of these functions to the caller
let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) };
let (size, alignment) = unsafe { (mem::size_of_val_raw(t), Alignment::of_val_raw(t)) };
// SAFETY: see rationale in `new` for why this is using the unsafe variant
unsafe { Layout::from_size_align_unchecked(size, align) }
unsafe { Layout::from_size_alignment_unchecked(size, alignment) }
}
/// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
@ -243,13 +289,33 @@ impl Layout {
#[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")]
#[inline]
pub const fn align_to(&self, align: usize) -> Result<Self, LayoutError> {
if let Some(align) = Alignment::new(align) {
Layout::from_size_alignment(self.size, Alignment::max(self.align, align))
if let Some(alignment) = Alignment::new(align) {
self.adjust_alignment_to(alignment)
} else {
Err(LayoutError)
}
}
/// Creates a layout describing the record that can hold a value
/// of the same layout as `self`, but that also is aligned to
/// alignment `alignment`.
///
/// If `self` already meets the prescribed alignment, then returns
/// `self`.
///
/// Note that this method does not add any padding to the overall
/// size, regardless of whether the returned layout has a different
/// alignment. In other words, if `K` has size 16, `K.align_to(32)`
/// will *still* have size 16.
///
/// Returns an error if the combination of `self.size()` and the given
/// `alignment` violates the conditions listed in [`Layout::from_size_alignment`].
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
pub const fn adjust_alignment_to(&self, alignment: Alignment) -> Result<Self, LayoutError> {
Layout::from_size_alignment(self.size, Alignment::max(self.align, alignment))
}
/// Returns the amount of padding we must insert after `self`
/// to ensure that the following address will satisfy `alignment`.
///
@ -267,7 +333,7 @@ impl Layout {
#[must_use = "this returns the padding needed, without modifying the `Layout`"]
#[inline]
pub const fn padding_needed_for(&self, alignment: Alignment) -> usize {
let len_rounded_up = self.size_rounded_up_to_custom_align(alignment);
let len_rounded_up = self.size_rounded_up_to_custom_alignment(alignment);
// SAFETY: Cannot overflow because the rounded-up value is never less
unsafe { unchecked_sub(len_rounded_up, self.size) }
}
@ -277,7 +343,7 @@ impl Layout {
/// This can return at most `Alignment::MAX` (aka `isize::MAX + 1`)
/// because the original size is at most `isize::MAX`.
#[inline]
const fn size_rounded_up_to_custom_align(&self, align: Alignment) -> usize {
const fn size_rounded_up_to_custom_alignment(&self, alignment: Alignment) -> usize {
// SAFETY:
// Rounded up value is:
// size_rounded_up = (size + align - 1) & !(align - 1);
@ -297,7 +363,7 @@ impl Layout {
// (Size 0 Align MAX is already aligned, so stays the same, but things like
// Size 1 Align MAX or Size isize::MAX Align 2 round up to `isize::MAX + 1`.)
unsafe {
let align_m1 = unchecked_sub(align.as_usize(), 1);
let align_m1 = unchecked_sub(alignment.as_usize(), 1);
unchecked_add(self.size, align_m1) & !align_m1
}
}
@ -317,10 +383,10 @@ impl Layout {
// > `size`, when rounded up to the nearest multiple of `align`,
// > must not overflow isize (i.e., the rounded value must be
// > less than or equal to `isize::MAX`)
let new_size = self.size_rounded_up_to_custom_align(self.align);
let new_size = self.size_rounded_up_to_custom_alignment(self.align);
// SAFETY: padded size is guaranteed to not exceed `isize::MAX`.
unsafe { Layout::from_size_align_unchecked(new_size, self.align()) }
unsafe { Layout::from_size_alignment_unchecked(new_size, self.alignment()) }
}
/// Creates a layout describing the record for `n` instances of
@ -426,8 +492,8 @@ impl Layout {
#[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")]
#[inline]
pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> {
let new_align = Alignment::max(self.align, next.align);
let offset = self.size_rounded_up_to_custom_align(next.align);
let new_alignment = Alignment::max(self.align, next.align);
let offset = self.size_rounded_up_to_custom_alignment(next.align);
// SAFETY: `offset` is at most `isize::MAX + 1` (such as from aligning
// to `Alignment::MAX`) and `next.size` is at most `isize::MAX` (from the
@ -435,7 +501,7 @@ impl Layout {
// `isize::MAX + 1 + isize::MAX`, which is `usize::MAX`, and cannot overflow.
let new_size = unsafe { unchecked_add(offset, next.size) };
if let Ok(layout) = Layout::from_size_alignment(new_size, new_align) {
if let Ok(layout) = Layout::from_size_alignment(new_size, new_alignment) {
Ok((layout, offset))
} else {
Err(LayoutError)
@ -496,7 +562,7 @@ impl Layout {
#[inline]
const fn inner(element_layout: Layout, n: usize) -> Result<Layout, LayoutError> {
let Layout { size: element_size, align } = element_layout;
let Layout { size: element_size, align: alignment } = element_layout;
// We need to check two things about the size:
// - That the total size won't overflow a `usize`, and
@ -504,7 +570,7 @@ impl Layout {
// By using division we can check them both with a single threshold.
// That'd usually be a bad idea, but thankfully here the element size
// and alignment are constants, so the compiler will fold all of it.
if element_size != 0 && n > Layout::max_size_for_align(align) / element_size {
if element_size != 0 && n > Layout::max_size_for_alignment(alignment) / element_size {
return Err(LayoutError);
}
@ -517,17 +583,9 @@ impl Layout {
// SAFETY: We just checked above that the `array_size` will not
// exceed `isize::MAX` even when rounded up to the alignment.
// And `Alignment` guarantees it's a power of two.
unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) }
unsafe { Ok(Layout::from_size_alignment_unchecked(array_size, alignment)) }
}
}
/// 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")]

View file

@ -9,6 +9,7 @@ use crate::alloc::Layout;
use crate::clone::TrivialClone;
use crate::marker::{Destruct, DiscriminantKind};
use crate::panic::const_assert;
use crate::ptr::Alignment;
use crate::{clone, cmp, fmt, hash, intrinsics, ptr};
mod manually_drop;
@ -1257,6 +1258,10 @@ pub trait SizedTypeProperties: Sized {
#[lang = "mem_align_const"]
const ALIGN: usize = intrinsics::align_of::<Self>();
#[doc(hidden)]
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
const ALIGNMENT: Alignment = Alignment::of::<Self>();
/// `true` if this type requires no storage.
/// `false` if its [size](size_of) is greater than zero.
///

View file

@ -1,5 +1,6 @@
#![allow(clippy::enum_clike_unportable_variant)]
use crate::marker::MetaSized;
use crate::num::NonZero;
use crate::ub_checks::assert_unsafe_precondition;
use crate::{cmp, fmt, hash, mem, num};
@ -50,6 +51,79 @@ impl Alignment {
const { Alignment::new(align_of::<T>()).unwrap() }
}
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
///
/// Every reference to a value of the type `T` must be a multiple of this number.
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
///
/// # Examples
///
/// ```
/// #![feature(ptr_alignment_type)]
/// use std::ptr::Alignment;
///
/// assert_eq!(Alignment::of_val(&5i32).as_usize(), 4);
/// ```
#[inline]
#[must_use]
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
pub const fn of_val<T: MetaSized>(val: &T) -> Self {
let align = mem::align_of_val(val);
// SAFETY: `align_of_val` returns valid alignment
unsafe { Alignment::new_unchecked(align) }
}
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
///
/// Every reference to a value of the type `T` must be a multiple of this number.
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
///
/// # Safety
///
/// This function is only safe to call if the following conditions hold:
///
/// - If `T` is `Sized`, this function is always safe to call.
/// - If the unsized tail of `T` is:
/// - a [slice], then the length of the slice tail must be an initialized
/// integer, and the size of the *entire value*
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
/// For the special case where the dynamic tail length is 0, this function
/// is safe to call.
/// - a [trait object], then the vtable part of the pointer must point
/// to a valid vtable acquired by an unsizing coercion, and the size
/// of the *entire value* (dynamic tail length + statically sized prefix)
/// must fit in `isize`.
/// - an (unstable) [extern type], then this function is always safe to
/// call, but may panic or otherwise return the wrong value, as the
/// extern type's layout is not known. This is the same behavior as
/// [`Alignment::of_val`] on a reference to a type with an extern type tail.
/// - otherwise, it is conservatively not allowed to call this function.
///
/// [trait object]: ../../book/ch17-02-trait-objects.html
/// [extern type]: ../../unstable-book/language-features/extern-types.html
///
/// # Examples
///
/// ```
/// #![feature(ptr_alignment_type)]
/// #![feature(layout_for_ptr)]
/// use std::ptr::Alignment;
///
/// assert_eq!(unsafe { Alignment::of_val_raw(&5i32) }.as_usize(), 4);
/// ```
#[inline]
#[must_use]
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
// #[unstable(feature = "layout_for_ptr", issue = "69835")]
pub const unsafe fn of_val_raw<T: MetaSized>(val: *const T) -> Self {
// SAFETY: precondition propagated to the caller
let align = unsafe { mem::align_of_val_raw(val) };
// SAFETY: `align_of_val_raw` returns valid alignment
unsafe { Alignment::new_unchecked(align) }
}
/// Creates an `Alignment` from a `usize`, or returns `None` if it's
/// not a power of two.
///

View file

@ -12,32 +12,32 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 3 {
let _8: std::ptr::alignment::AlignmentEnum;
scope 4 {
scope 12 (inlined Layout::size) {
scope 17 (inlined Layout::size) {
}
scope 13 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 14 (inlined NonNull::<[T]>::cast::<u8>) {
scope 15 (inlined NonNull::<[T]>::as_ptr) {
scope 18 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 19 (inlined NonNull::<[T]>::cast::<u8>) {
scope 20 (inlined NonNull::<[T]>::as_ptr) {
}
}
}
scope 16 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 17 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
scope 21 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 22 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
}
}
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 19 (inlined std::alloc::Global::deallocate_impl) {
scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) {
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 21 (inlined Layout::size) {
scope 26 (inlined Layout::size) {
}
scope 22 (inlined NonNull::<u8>::as_ptr) {
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 23 (inlined std::alloc::dealloc) {
scope 28 (inlined std::alloc::dealloc) {
let mut _10: usize;
scope 24 (inlined Layout::size) {
scope 29 (inlined Layout::size) {
}
scope 25 (inlined Layout::align) {
scope 26 (inlined std::ptr::Alignment::as_usize) {
scope 30 (inlined Layout::align) {
scope 31 (inlined std::ptr::Alignment::as_usize) {
}
}
}
@ -51,15 +51,25 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
}
scope 7 (inlined Layout::for_value_raw::<[T]>) {
let mut _5: usize;
let mut _6: usize;
let mut _7: std::ptr::Alignment;
scope 8 {
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let mut _7: std::ptr::Alignment;
scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) {
}
}
scope 9 (inlined size_of_val_raw::<[T]>) {
}
scope 10 (inlined align_of_val_raw::<[T]>) {
scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) {
let _6: usize;
scope 11 {
scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) {
scope 14 (inlined core::ub_checks::check_language_ub) {
scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
}
}
}
}
scope 12 (inlined align_of_val_raw::<[T]>) {
}
}
}
}
@ -72,17 +82,17 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
StorageLive(_4);
_3 = copy _2 as *mut [T] (Transmute);
_4 = copy _2 as *const [T] (Transmute);
StorageLive(_6);
StorageLive(_7);
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageLive(_6);
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
StorageLive(_7);
_7 = copy _6 as std::ptr::Alignment (Transmute);
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_6);
_8 = copy (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
}

View file

@ -12,32 +12,32 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 3 {
let _8: std::ptr::alignment::AlignmentEnum;
scope 4 {
scope 12 (inlined Layout::size) {
scope 17 (inlined Layout::size) {
}
scope 13 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 14 (inlined NonNull::<[T]>::cast::<u8>) {
scope 15 (inlined NonNull::<[T]>::as_ptr) {
scope 18 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 19 (inlined NonNull::<[T]>::cast::<u8>) {
scope 20 (inlined NonNull::<[T]>::as_ptr) {
}
}
}
scope 16 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 17 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
scope 21 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 22 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
}
}
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 19 (inlined std::alloc::Global::deallocate_impl) {
scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) {
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 21 (inlined Layout::size) {
scope 26 (inlined Layout::size) {
}
scope 22 (inlined NonNull::<u8>::as_ptr) {
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 23 (inlined std::alloc::dealloc) {
scope 28 (inlined std::alloc::dealloc) {
let mut _10: usize;
scope 24 (inlined Layout::size) {
scope 29 (inlined Layout::size) {
}
scope 25 (inlined Layout::align) {
scope 26 (inlined std::ptr::Alignment::as_usize) {
scope 30 (inlined Layout::align) {
scope 31 (inlined std::ptr::Alignment::as_usize) {
}
}
}
@ -51,15 +51,25 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
}
scope 7 (inlined Layout::for_value_raw::<[T]>) {
let mut _5: usize;
let mut _6: usize;
let mut _7: std::ptr::Alignment;
scope 8 {
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let mut _7: std::ptr::Alignment;
scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) {
}
}
scope 9 (inlined size_of_val_raw::<[T]>) {
}
scope 10 (inlined align_of_val_raw::<[T]>) {
scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) {
let _6: usize;
scope 11 {
scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) {
scope 14 (inlined core::ub_checks::check_language_ub) {
scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
}
}
}
}
scope 12 (inlined align_of_val_raw::<[T]>) {
}
}
}
}
@ -72,17 +82,17 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
StorageLive(_4);
_3 = copy _2 as *mut [T] (Transmute);
_4 = copy _2 as *const [T] (Transmute);
StorageLive(_6);
StorageLive(_7);
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageLive(_6);
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
StorageLive(_7);
_7 = copy _6 as std::ptr::Alignment (Transmute);
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_6);
_8 = copy (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
}

View file

@ -12,32 +12,32 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 3 {
let _8: std::ptr::alignment::AlignmentEnum;
scope 4 {
scope 12 (inlined Layout::size) {
scope 17 (inlined Layout::size) {
}
scope 13 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 14 (inlined NonNull::<[T]>::cast::<u8>) {
scope 15 (inlined NonNull::<[T]>::as_ptr) {
scope 18 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 19 (inlined NonNull::<[T]>::cast::<u8>) {
scope 20 (inlined NonNull::<[T]>::as_ptr) {
}
}
}
scope 16 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 17 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
scope 21 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 22 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
}
}
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 19 (inlined std::alloc::Global::deallocate_impl) {
scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) {
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 21 (inlined Layout::size) {
scope 26 (inlined Layout::size) {
}
scope 22 (inlined NonNull::<u8>::as_ptr) {
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 23 (inlined std::alloc::dealloc) {
scope 28 (inlined std::alloc::dealloc) {
let mut _10: usize;
scope 24 (inlined Layout::size) {
scope 29 (inlined Layout::size) {
}
scope 25 (inlined Layout::align) {
scope 26 (inlined std::ptr::Alignment::as_usize) {
scope 30 (inlined Layout::align) {
scope 31 (inlined std::ptr::Alignment::as_usize) {
}
}
}
@ -51,15 +51,25 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
}
scope 7 (inlined Layout::for_value_raw::<[T]>) {
let mut _5: usize;
let mut _6: usize;
let mut _7: std::ptr::Alignment;
scope 8 {
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let mut _7: std::ptr::Alignment;
scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) {
}
}
scope 9 (inlined size_of_val_raw::<[T]>) {
}
scope 10 (inlined align_of_val_raw::<[T]>) {
scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) {
let _6: usize;
scope 11 {
scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) {
scope 14 (inlined core::ub_checks::check_language_ub) {
scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
}
}
}
}
scope 12 (inlined align_of_val_raw::<[T]>) {
}
}
}
}
@ -72,17 +82,17 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
StorageLive(_4);
_3 = copy _2 as *mut [T] (Transmute);
_4 = copy _2 as *const [T] (Transmute);
StorageLive(_6);
StorageLive(_7);
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageLive(_6);
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
StorageLive(_7);
_7 = copy _6 as std::ptr::Alignment (Transmute);
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_6);
_8 = copy (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
}

View file

@ -12,32 +12,32 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
scope 3 {
let _8: std::ptr::alignment::AlignmentEnum;
scope 4 {
scope 12 (inlined Layout::size) {
scope 17 (inlined Layout::size) {
}
scope 13 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 14 (inlined NonNull::<[T]>::cast::<u8>) {
scope 15 (inlined NonNull::<[T]>::as_ptr) {
scope 18 (inlined std::ptr::Unique::<[T]>::cast::<u8>) {
scope 19 (inlined NonNull::<[T]>::cast::<u8>) {
scope 20 (inlined NonNull::<[T]>::as_ptr) {
}
}
}
scope 16 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 17 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
scope 21 (inlined <NonNull<u8> as From<std::ptr::Unique<u8>>>::from) {
scope 22 (inlined std::ptr::Unique::<u8>::as_non_null_ptr) {
}
}
scope 18 (inlined <std::alloc::Global as Allocator>::deallocate) {
scope 19 (inlined std::alloc::Global::deallocate_impl) {
scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) {
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 21 (inlined Layout::size) {
scope 26 (inlined Layout::size) {
}
scope 22 (inlined NonNull::<u8>::as_ptr) {
scope 27 (inlined NonNull::<u8>::as_ptr) {
}
scope 23 (inlined std::alloc::dealloc) {
scope 28 (inlined std::alloc::dealloc) {
let mut _10: usize;
scope 24 (inlined Layout::size) {
scope 29 (inlined Layout::size) {
}
scope 25 (inlined Layout::align) {
scope 26 (inlined std::ptr::Alignment::as_usize) {
scope 30 (inlined Layout::align) {
scope 31 (inlined std::ptr::Alignment::as_usize) {
}
}
}
@ -51,15 +51,25 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
}
scope 7 (inlined Layout::for_value_raw::<[T]>) {
let mut _5: usize;
let mut _6: usize;
let mut _7: std::ptr::Alignment;
scope 8 {
scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let mut _7: std::ptr::Alignment;
scope 16 (inlined #[track_caller] Layout::from_size_alignment_unchecked) {
}
}
scope 9 (inlined size_of_val_raw::<[T]>) {
}
scope 10 (inlined align_of_val_raw::<[T]>) {
scope 10 (inlined std::ptr::Alignment::of_val_raw::<[T]>) {
let _6: usize;
scope 11 {
scope 13 (inlined #[track_caller] std::ptr::Alignment::new_unchecked) {
scope 14 (inlined core::ub_checks::check_language_ub) {
scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
}
}
}
}
scope 12 (inlined align_of_val_raw::<[T]>) {
}
}
}
}
@ -72,17 +82,17 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () {
StorageLive(_4);
_3 = copy _2 as *mut [T] (Transmute);
_4 = copy _2 as *const [T] (Transmute);
StorageLive(_6);
StorageLive(_7);
_5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageLive(_6);
_6 = const <T as std::mem::SizedTypeProperties>::ALIGN;
StorageLive(_7);
_7 = copy _6 as std::ptr::Alignment (Transmute);
_8 = move (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_6);
_8 = copy (_7.0: std::ptr::alignment::AlignmentEnum);
StorageDead(_7);
StorageDead(_4);
switchInt(copy _5) -> [0: bb4, otherwise: bb2];
}

View file

@ -11,7 +11,7 @@ pub unsafe fn generic_in_place<T: Copy>(ptr: *mut Box<[T]>) {
// CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]>
// CHECK: [[ALIGN:_.+]] = const <T as std::mem::SizedTypeProperties>::ALIGN;
// CHECK: [[B:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute);
// CHECK: [[C:_.+]] = move ([[B]].0: std::ptr::alignment::AlignmentEnum);
// CHECK: [[C:_.+]] = copy ([[B]].0: std::ptr::alignment::AlignmentEnum);
// CHECK: [[D:_.+]] = discriminant([[C]]);
// CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[D]]) ->
std::ptr::drop_in_place(ptr)

View file

@ -68,7 +68,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::concrete).10)
span: $DIR/offset_of.rs:37:5: 1440:57 (#0)
span: $DIR/offset_of.rs:37:5: 1445:57 (#0)
}
}
Stmt {
@ -117,7 +117,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::concrete).20)
span: $DIR/offset_of.rs:38:5: 1440:57 (#0)
span: $DIR/offset_of.rs:38:5: 1445:57 (#0)
}
}
Stmt {
@ -166,7 +166,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::concrete).30)
span: $DIR/offset_of.rs:39:5: 1440:57 (#0)
span: $DIR/offset_of.rs:39:5: 1445:57 (#0)
}
}
Stmt {
@ -215,7 +215,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::concrete).40)
span: $DIR/offset_of.rs:40:5: 1440:57 (#0)
span: $DIR/offset_of.rs:40:5: 1445:57 (#0)
}
}
Stmt {
@ -264,7 +264,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::concrete).50)
span: $DIR/offset_of.rs:41:5: 1440:57 (#0)
span: $DIR/offset_of.rs:41:5: 1445:57 (#0)
}
}
]
@ -864,7 +864,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::generic).12)
span: $DIR/offset_of.rs:45:5: 1440:57 (#0)
span: $DIR/offset_of.rs:45:5: 1445:57 (#0)
}
}
Stmt {
@ -913,7 +913,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::generic).24)
span: $DIR/offset_of.rs:46:5: 1440:57 (#0)
span: $DIR/offset_of.rs:46:5: 1445:57 (#0)
}
}
Stmt {
@ -962,7 +962,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::generic).36)
span: $DIR/offset_of.rs:47:5: 1440:57 (#0)
span: $DIR/offset_of.rs:47:5: 1445:57 (#0)
}
}
Stmt {
@ -1011,7 +1011,7 @@ body:
)
else_block: None
hir_id: HirId(DefId(offset_of::generic).48)
span: $DIR/offset_of.rs:48:5: 1440:57 (#0)
span: $DIR/offset_of.rs:48:5: 1445:57 (#0)
}
}
]