Skip to content

Document valid pointer and Box transmutations#2282

Open
traviscross wants to merge 6 commits into
masterfrom
TC/box-transmute-validity
Open

Document valid pointer and Box transmutations#2282
traviscross wants to merge 6 commits into
masterfrom
TC/box-transmute-validity

Conversation

@traviscross

@traviscross traviscross commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

The pointer-to-pointer cast rules and the wide-pointer validity rule
both speak of the *metadata* of a pointer, but we hadn't explicitly
defined the term (even though we had defined the contents of that
metadata).  Let's do that and link to it.
We refer to the unsized tail of a type, but we hadn't defined it.
Let's do that and link to the definition.
@traviscross traviscross force-pushed the TC/box-transmute-validity branch from e75977e to b624dd7 Compare June 9, 2026 20:04
* Pointers to trait objects also store a pointer to a vtable.
* [Pointer types] to <abbr title="dynamically sized types">DSTs</abbr> are sized but have twice the size of pointers to sized types, since they also store *metadata*:
* Pointers to slices store the number of elements; pointers to `str` store the length in bytes.
* Pointers to trait objects store a pointer to a vtable.

@Mark-Simulacrum Mark-Simulacrum Jun 9, 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.

Comparing notes with https://doc.rust-lang.org/nightly/std/ptr/trait.Pointee.html#pointer-metadata, I think the only missing piece is the "unsized / last field" indirection for indirectly unsized types.

View changes since the review

Comment thread src/behavior-considered-undefined.md Outdated
* The [metadata] of a wide reference, [`Box<T>`], or raw pointer must match the type of the unsized tail:
* The [metadata] of a wide reference, [`Box<T>`], or raw pointer must match the type of the [unsized tail]:
* `dyn Trait` metadata must be a pointer to a compiler-generated vtable for `Trait`. (For raw pointers, this requirement remains a subject of some debate.)
* Slice (`[T]`) metadata must be a valid `usize`. Furthermore, for wide references and [`Box<T>`], slice metadata is invalid if it makes the total size of the pointed-to value bigger than `isize::MAX`.

@Mark-Simulacrum Mark-Simulacrum Jun 9, 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.

  • This is missing the str case.
  • The "invalid if total size" seems like it applies more generally to all metadata, including indirectly stored size metadata in the vtable? Though that becomes complicated since it depends on a deref to determine that the original thing is valid.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(As context for others, this is preexisting text.)

On the first point, thanks; I've added that.

On the second, the text requires that, for dyn Trait, the "metadata must be a pointer to a compiler-generated vtable for Trait". Given that, think we still need to place further requirements on its contents?

Comment thread src/special-types-and-traits.md Outdated
Comment thread src/type-layout.md
tail: T,
}
// Pointers to two types share a layout when the types are both sized,
// both have a slice or `str` tail, or both have a trait object tail.

@Mark-Simulacrum Mark-Simulacrum Jun 9, 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.

Hm, I guess the pointers would share a layout even under -Zrandomize-layout? Though that may not guarantee transmutes are sound (since alignment could change).

View changes since the review

@traviscross traviscross added T-lang Relevant to the language team. needs-fcp labels Jun 9, 2026
@traviscross traviscross force-pushed the TC/box-transmute-validity branch from b624dd7 to 5a667b1 Compare June 9, 2026 20:23
Comment thread src/type-layout.md Outdated
<!-- Editor Note: This is nowhere close to an exhaustive list -->

r[lang-types.box.transmute]
For types `T` and `U` such that `*mut T` and `*mut U` have the same layout (per [layout.pointer.parametric]) and a [pointer-to-pointer cast] from `*mut T` to `*mut U` is permitted, transmuting a `Box<T>` to a `Box<U>`, where both boxes use the global allocator, is sound when both of the following hold:

@ehuss ehuss Jun 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just curious, why "global" here?

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.

Box with a custom allocator is not necessarily going to put the allocator in the same place -- e.g. under -Zrandomize-layout -- for different value types, so I don't think we can make this guarantee. Maybe it can be made for 1-ZST allocators? Not sure...

We guarantee various things about the layout of pointers and
references, but we'd made no guarantees of equivalence between two
pointers to distinct unsized types that differ in the unsized tail.
Let's make some useful guarantees about this.
Our rules for `as` casts document which pointer-to-pointer casts are
valid.  For unsized types, this validity is based on the compatibility
of the pointer metadata.  Using this and our layout equivalences, we
can define when a pointer transmute will produce the same pointer
value as would a cast.  Let's define that.
We hadn't documented when it's sound to transmute a `Box<T>` to a
`Box<U>`.  Now that we've documented when `*mut T` and `*mut U` can be
assumed to have the same layout, let's use that to document when this
transmute is sound.
The validity rule for the metadata of a wide reference, `Box<T>`,
or raw pointer mentions `dyn Trait` and slice but had omitted
`str`.  Let's fix that.
@traviscross traviscross force-pushed the TC/box-transmute-validity branch from 5a667b1 to 6ca17b8 Compare June 10, 2026 07:41
@traviscross traviscross marked this pull request as ready for review June 10, 2026 07:44
@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Jun 10, 2026
@traviscross

Copy link
Copy Markdown
Contributor Author

cc @RalfJung

@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. T-opsem Team: opsem labels Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

I-lang-nominated Nominated for discussion during a lang team meeting. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. needs-fcp P-lang-drag-1 Lang team prioritization drag level 1. S-waiting-on-review Status: The marked PR is awaiting review from a maintainer T-lang Relevant to the language team. T-opsem Team: opsem

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants