diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f58ebd488d7ca..cec41524325e0 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -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(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::>(); - layout.size() + layout.padding_needed_for(align) + layout.size() + layout.padding_needed_for(alignment) } /// A uniquely owned [`Rc`]. @@ -4478,7 +4478,7 @@ impl UniqueRcUninit { /// 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 } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index fc44a468c8a41..a5e4fab916aba 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -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(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::>(); - 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 UniqueArcUninit { /// 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 } } diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 3a2111350a4ed..4bffdd17696fb 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -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 { - if size > Self::max_size_for_align(align) { - return Err(LayoutError); + pub const fn from_size_alignment( + size: usize, + alignment: Alignment, + ) -> Result { + 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: &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: *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 { - 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 { + 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 { - 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")] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 1671c8219de16..7c486875a8268 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -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::(); + #[doc(hidden)] + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + const ALIGNMENT: Alignment = Alignment::of::(); + /// `true` if this type requires no storage. /// `false` if its [size](size_of) is greater than zero. /// diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bc7d3a1de7151..42c95e6c9cd25 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -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::()).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(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(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. /// diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir index 013361d1d2fb8..7066527cf76d7 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir @@ -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 Unique::<[T]>::cast::) { - scope 14 (inlined NonNull::<[T]>::cast::) { - scope 15 (inlined NonNull::<[T]>::as_ptr) { + scope 18 (inlined Unique::<[T]>::cast::) { + scope 19 (inlined NonNull::<[T]>::cast::) { + scope 20 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 16 (inlined as From>>::from) { - scope 17 (inlined Unique::::as_non_null_ptr) { + scope 21 (inlined as From>>::from) { + scope 22 (inlined Unique::::as_non_null_ptr) { } } - scope 18 (inlined ::deallocate) { - scope 19 (inlined std::alloc::Global::deallocate_impl) { - scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 23 (inlined ::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::::as_ptr) { + scope 27 (inlined NonNull::::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 ::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]; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir index 013361d1d2fb8..7066527cf76d7 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir @@ -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 Unique::<[T]>::cast::) { - scope 14 (inlined NonNull::<[T]>::cast::) { - scope 15 (inlined NonNull::<[T]>::as_ptr) { + scope 18 (inlined Unique::<[T]>::cast::) { + scope 19 (inlined NonNull::<[T]>::cast::) { + scope 20 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 16 (inlined as From>>::from) { - scope 17 (inlined Unique::::as_non_null_ptr) { + scope 21 (inlined as From>>::from) { + scope 22 (inlined Unique::::as_non_null_ptr) { } } - scope 18 (inlined ::deallocate) { - scope 19 (inlined std::alloc::Global::deallocate_impl) { - scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 23 (inlined ::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::::as_ptr) { + scope 27 (inlined NonNull::::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 ::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]; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir index 013361d1d2fb8..7066527cf76d7 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir @@ -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 Unique::<[T]>::cast::) { - scope 14 (inlined NonNull::<[T]>::cast::) { - scope 15 (inlined NonNull::<[T]>::as_ptr) { + scope 18 (inlined Unique::<[T]>::cast::) { + scope 19 (inlined NonNull::<[T]>::cast::) { + scope 20 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 16 (inlined as From>>::from) { - scope 17 (inlined Unique::::as_non_null_ptr) { + scope 21 (inlined as From>>::from) { + scope 22 (inlined Unique::::as_non_null_ptr) { } } - scope 18 (inlined ::deallocate) { - scope 19 (inlined std::alloc::Global::deallocate_impl) { - scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 23 (inlined ::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::::as_ptr) { + scope 27 (inlined NonNull::::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 ::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]; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir index 013361d1d2fb8..7066527cf76d7 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir @@ -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 Unique::<[T]>::cast::) { - scope 14 (inlined NonNull::<[T]>::cast::) { - scope 15 (inlined NonNull::<[T]>::as_ptr) { + scope 18 (inlined Unique::<[T]>::cast::) { + scope 19 (inlined NonNull::<[T]>::cast::) { + scope 20 (inlined NonNull::<[T]>::as_ptr) { } } } - scope 16 (inlined as From>>::from) { - scope 17 (inlined Unique::::as_non_null_ptr) { + scope 21 (inlined as From>>::from) { + scope 22 (inlined Unique::::as_non_null_ptr) { } } - scope 18 (inlined ::deallocate) { - scope 19 (inlined std::alloc::Global::deallocate_impl) { - scope 20 (inlined std::alloc::Global::deallocate_impl_runtime) { + scope 23 (inlined ::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::::as_ptr) { + scope 27 (inlined NonNull::::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 ::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]; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs index 83b10f8bd6888..dddcffdd48439 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs @@ -11,7 +11,7 @@ pub unsafe fn generic_in_place(ptr: *mut Box<[T]>) { // CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]> // CHECK: [[ALIGN:_.+]] = const ::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) diff --git a/tests/ui/thir-print/offset_of.stdout b/tests/ui/thir-print/offset_of.stdout index b3791a2446cb4..5666a5972f371 100644 --- a/tests/ui/thir-print/offset_of.stdout +++ b/tests/ui/thir-print/offset_of.stdout @@ -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) } } ]