Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@
#![feature(io_const_error_internals)]
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
#![feature(layout_for_ptr)]
#![feature(legacy_receiver_trait)]
#![feature(likely_unlikely)]
#![feature(local_waker)]
Expand Down
28 changes: 16 additions & 12 deletions library/core/src/alloc/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,24 +230,28 @@ impl Layout {
///
/// - 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*
/// - a [slice] `[U]`, `str`, or a [trait object] `dyn Trait`, then 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 for the type `T` 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
/// [`Layout::for_value`] on a reference to an extern type tail.
/// - otherwise, it is conservatively not allowed to call this function.
// NOTE: the reason this is safe is that if an overflow were to occur already with size 0,
// then we would stop compilation as even the "statically known" part of the type would
// already be too big (or the call may be in dead code and optimized away, but then it
// doesn't matter).
/// - No other kind of unsized tail currently exists that satisfies the trait bounds for this
/// function. If more kinds of unsized tails get introduced in the future, the documentation
/// of this function will have to be extended before it can be used for such types.
///
/// Here, *unsized tail* refers to the type obtained by recursively descending through the last
/// field of a tuple or struct until we arrived at a built-in unsized type.
Comment on lines +245 to +246

@Darksonn Darksonn Jul 8, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tuples with unsized tails were removed from the language in #137728.

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Errr ... actually forget about that. We just removed the coercion and the promise that (i32, i32) and (i32, dyn Send) have compatible layouts, but (i32, dyn Send) is still technically a type that exists in the language.

So forget about this comment.

///
/// As a consequence of these rules, it is the case that whenever it is allowed to convert `val`
/// into a shared reference, then it is also allowed to invoke this function.
///
/// [trait object]: ../../book/ch17-02-trait-objects.html
/// [extern type]: ../../unstable-book/language-features/extern-types.html
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[stable(feature = "layout_for_ptr", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "layout_for_ptr", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
Expand Down
56 changes: 29 additions & 27 deletions library/core/src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,25 +422,24 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
/// 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*
/// - If the *unsized tail* of `T` is:
/// - a [slice] `[U]`, `str`, or a [trait object] `dyn Trait`, then 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.
// NOTE: the reason this is safe is that if an overflow were to occur already with size 0,
// then we would stop compilation as even the "statically known" part of the type would
// already be too big (or the call may be in dead code and optimized away, but then it
// doesn't matter).
/// - 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
/// [`size_of_val`] on a reference to a type with an extern type tail.
/// - otherwise, it is conservatively not allowed to call this function.
/// - No other kind of unsized tail currently exists that satisfies the trait bounds for this
/// function. If more kinds of unsized tails get introduced in the future, the documentation
/// of this function will have to be extended before it can be used for such types.
///
/// Here, *unsized tail* refers to the type obtained by recursively descending through the last
/// field of a tuple or struct until we arrived at a built-in unsized type.
///
/// As a consequence of these rules, it is the case that whenever it is allowed to convert `val`
/// into a shared reference, then it is also allowed to invoke this function.
///
/// [`size_of::<T>()`]: size_of
/// [trait object]: ../../book/ch17-02-trait-objects.html
Expand All @@ -449,7 +448,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
/// # Examples
///
/// ```
/// #![feature(layout_for_ptr)]
/// use std::mem;
///
/// assert_eq!(4, size_of_val(&5i32));
Expand All @@ -460,7 +458,8 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
/// ```
#[inline]
#[must_use]
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[stable(feature = "layout_for_ptr", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "layout_for_ptr", since = "CURRENT_RUSTC_VERSION")]
pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
// SAFETY: the caller must provide a valid raw pointer
unsafe { intrinsics::size_of_val(val) }
Expand Down Expand Up @@ -596,28 +595,30 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
///
/// - 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*
/// - a [slice] `[U]`, `str`, or a [trait object] `dyn Trait`, then 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
/// [`align_of_val`] on a reference to a type with an extern type tail.
/// - otherwise, it is conservatively not allowed to call this function.
// NOTE: the reason this is safe is that if an overflow were to occur already with size 0,
// then we would stop compilation as even the "statically known" part of the type would
// already be too big (or the call may be in dead code and optimized away, but then it
// doesn't matter).
/// - No other kind of unsized tail currently exists that satisfies the trait bounds for this
/// function. If more kinds of unsized tails get introduced in the future, the documentation
/// of this function will have to be extended before it can be used for such types.
///
/// Here, *unsized tail* refers to the type obtained by recursively descending through the last
/// field of a tuple or struct until we arrived at a built-in unsized type.
///
/// As a consequence of these rules, it is the case that whenever it is allowed to convert `val`
/// into a shared reference, then it is also allowed to invoke this function.
///
/// [trait object]: ../../book/ch17-02-trait-objects.html
/// [extern type]: ../../unstable-book/language-features/extern-types.html
///
/// # Examples
///
/// ```
/// #![feature(layout_for_ptr)]
/// use std::mem;
///
/// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) });
Expand All @@ -629,7 +630,8 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
/// [type-layout]: ../../reference/type-layout.html#r-layout.primitive
#[inline]
#[must_use]
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[stable(feature = "layout_for_ptr", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "layout_for_ptr", since = "CURRENT_RUSTC_VERSION")]
pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
// SAFETY: the caller must provide a valid raw pointer
unsafe { intrinsics::align_of_val(val) }
Expand Down
1 change: 0 additions & 1 deletion library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
#![feature(iter_partition_in_place)]
#![feature(iterator_try_collect)]
#![feature(iterator_try_reduce)]
#![feature(layout_for_ptr)]
#![feature(macro_metavar_expr_concat)]
#![feature(maybe_uninit_fill)]
#![feature(maybe_uninit_uninit_array_transpose)]
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/pass/intrinsics/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//@compile-flags: -Zmiri-permissive-provenance
#![feature(core_intrinsics, layout_for_ptr, ptr_metadata)]
#![feature(core_intrinsics, ptr_metadata)]
//! Tests for various intrinsics that do not fit anywhere else.

use std::intrinsics;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(layout_for_ptr)]
use std::mem;

#[repr(packed, C)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(layout_for_ptr)]
use std::mem;

#[repr(packed(4))]
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/pass/issues/issue-miri-2123.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(ptr_metadata, layout_for_ptr)]
#![feature(ptr_metadata)]

use std::{mem, ptr};

Expand Down
1 change: 0 additions & 1 deletion src/tools/miri/tests/pass/slices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
//@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes
//@compile-flags: -Zmiri-strict-provenance
#![feature(slice_partition_dedup)]
#![feature(layout_for_ptr)]

use std::{ptr, slice};

Expand Down
2 changes: 0 additions & 2 deletions tests/ui/consts/const-size_of_val-align_of_val.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//@ run-pass

#![feature(layout_for_ptr)]

use std::{mem, ptr};

struct Foo(#[allow(dead_code)] u32);
Expand Down
1 change: 0 additions & 1 deletion tests/ui/packed/issue-118537-field-offset-ice.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//@ run-pass
#![feature(layout_for_ptr)]
use std::mem;

#[repr(packed(4))]
Expand Down
1 change: 0 additions & 1 deletion tests/ui/packed/issue-118537-field-offset.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//@ run-pass
#![feature(layout_for_ptr)]
use std::mem;

#[repr(packed, C)]
Expand Down
Loading