Support DST pointer casts in `const fn`
- Dominant language
- Rust
- Stars
- 2.6k
- Forks
- 179
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 29
Description
The following is not valid:
```rust
fn cast(t: *mut T) -> *mut U {
t as *mut U
}
```
Rust isn't able to guarantee that `T` and `U` have the same "vtable kinds", and thus isn't able to prove that `*mut T` and `*mut U` have compatible pointer metadata. We currently work around this using this method on `KnownLayout`:
https://github.com/google/zerocopy/blob/0fae530a5b2e0566064548ed59f4918d424fd01b/src/lib.rs#L731
This has a limitation: It can't be called in a `const` context.
Instead, we could make casting unsafe, requiring the caller to promise to ensure that the pointers are either both thin or both fat, and use a union-transmute under the hood to avoid the vtable problem:
```rust
/// # Safety
///
/// The caller must ensure that `Src` and `Dst` must either both be `Sized` or
/// both be unsized.
const unsafe fn cast_unchecked(src: *mut Src) -> *mut Dst {
#[repr(C)]
union Transmute {
src: Src,
dst: Dst,
}
unsafe { Transmute { src }.dst }
}
```
The behavior of this union-transmute is *almost* well-defined, but not quite. The Reference [guarantees the behavior of raw pointer casts](https://doc.rust-lang.org/1.82.0/reference/expressions/operator-expr.html#pointer-to-pointer-cast), but makes no guarantee that the equivalent transmute has the same behavior as a cast. I've put up a PR to guarantee that this is well-defined: https://github.com/rust-lang/reference/pull/1661
Contributor guide
Assessment
This issue has not been assessed yet.