8000 Support DST pointer casts in `const fn` · Issue #1967 · google/zerocopy · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Support DST pointer casts in const fn #1967
Open
@joshlf

Description

@joshlf

The following is not valid:

fn cast<T: ?Sized, U: ?Sized>(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:

fn raw_from_ptr_len(bytes: NonNull<u8>, meta: Self::PointerMetadata) -> NonNull<Self>;

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:

/// # Safety
///
/// The caller must ensure that `Src` and `Dst` must either both be `Sized` or
/// both be unsized.
const unsafe fn cast_unchecked<Src: ?Sized, Dst: ?Sized>(src: *mut Src) -> *mut Dst {
    #[repr(C)]
    union Transmute<Src: Copy, Dst: Copy> {
        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, 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: rust-lang/reference#1661

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0