Skip to content

Statically prevent ZST slices rather than panicking at runtime? #325

Closed
@joshlf

Description

@joshlf

zerocopy/src/lib.rs

Lines 1731 to 1735 in 07854bc

pub fn new_slice(bytes: B) -> Option<Ref<B, [T]>> {
let remainder = bytes
.len()
.checked_rem(mem::size_of::<T>())
.expect("Ref::new_slice called on a zero-sized type");

Alternatively, maybe we could just give these types well-defined semantics (e.g., always synthesize a pointer with 0 slice elements or isize::MAX slice elements). Need to be very careful that none of our operations can be round-tripped losslessly; this might break that.

There are also reasons to be skeptical of wanting to prevent this at all:

In theory I like the idea of being able to have code like this fail at compile time. However, what do you do about a user who wants to write code like this?

pub fn do_thing<T: ?Sized + KnownLayout>() {
    if T::LAYOUT.trailing_slice_elem_type == Some(0) {
        // Do workaround thing
    } else {
        // Do other thing
    }
}

As in, you can't say that it's a compile-time error to have code that could trigger this panic because the user might have their own logic that ensures it'll never be encountered at runtime.

As of this writing, per #1149, we intend to use post-monomorphization errors for ZST slice conversions. We can always make our restrictions looser in the future. If we do decide to loosen restrictions, note the following caveats:

  • We cannot support "exact" conversions since those promise to produce a reference to the entire input byte sequence
  • We can support prefix and suffix conversions, but we will need to relax their semantics. Currently, prefix and suffix conversions promise to produce the "largest possible" value that will fit in the given byte sequence. While we could in principle argue that a slice with the maximum number of elements satisfies this promise, it clearly violates the spirit. It would likely make more sense to explicitly carve out ZST slices in the documentation.

See also #202, #284, #349 (comment), #1125, and #1149

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions