-
Notifications
You must be signed in to change notification settings - Fork 142
Description
Migrated from https://fxbug.dev/82795
See also: #1316.
The zerocopy transmute! macro can only be called in a context in which both the input and output types are concrete. As suggested in this comment (reproduced below), it should be possible to make a transmute function which can operate on generic types. This would require a substantial increase to zerocopy's API surface, and more code in zerocopy-derive, so it should only be done if a use case arises.
Copy of the comment:
One way you could get rid of this is by adding a
unsafe trait FromByteSized<const SIZE: usize>: FromBytes + Sized {}that your derive macros generate, and then implement your transmute function as
fn transmute<T, U, const N: usize>(x: T) where T: AsBytesSized<N>, U: FromBytesSized<N>, { let eyepatch = ManuallyDrop::new(x); unsafe { mem::transmute_copy(&*eyepatch) } }If no type parameters are provided, Rust will correctly infer this, although you cannot yet write something like
transmute::<_, U, _>(). This behavior isn't any better than the macro, but it makes it a Real Function at least. It is unclear to what degree this can be made to work in a generic context... probably propagating those bounds and the extra const parameter is "enough".In the future, you could have
AsBytesSized<N>provide aninto_bytes()function that produces an unaligned[u8; N].
I took a quick stab at implementing a prototype of this (using a separate Size<const N: usize> trait), and ran into a few problems:
- While it technically supports generics, if one of the types is concrete and the other is generic, the generic type must have a bound of the form
Size<N>whereNis a compile-time constant. You'd end up with a bound likeT: FromBytes + Size<60>. Not the end of the world, but kind of ugly. - I can't figure out how to implement
Sizefor arrays. There's no way to perform multiplication in a const generic context, so the following is illegal:impl<T> Size<0> for [T; 0] {} // OK impl<T: Size<N>, const N: usize> Size<N> for [T; 1] {} // OK impl<T: Size<N>, const N: usize> Size<{ N * 2 }> for [T; 2] {} // Illegal