Lokathor/bytemuck

Implement `Pod` for Tuples

botahamec opened this issue · 3 comments

As far as I can tell, this should be sound, as long as T always refers to the same type:

unsafe impl<T: Pod> for (T, T) {}

Am I correct? This doesn't seem like this should produce any padding bytes.

Unfortunately no, this is not allowed in general.

Tuples count as repr(rust), so the compiler might insert padding within the struct. Generally it won't, but it's allowed to.

For example, if T was [u8;3] the compiler is allowed to insert a padding byte after each field and then align the whole struct to 8, so that it can use wider memory instructions to read/write the entire tuple at once. Currently it does not do this in practice, but any future release might add such an optimization (trading space for more speed).

Unless there's a very specific guarantee about a type (such as Option<NonZeroU32> having identical layout as u32) then it's not wise to use any repr(rust) type with the bytemuck crate. For example, with slices this crate takes care to call the approved methods for disassembling and reassembling a slice, instead of directly transmuting the slice, even if the elements are the same size and everything.

@Lokathor Thanks. I ask because I was trying to derive Pod on a struct like this:

#[repr(C)]
struct Foo {
    position: (f32, f32)
}

What I was missing was that the tuple could only work that way for repr(C) types. Thanks for answering.

Ah yeah. The usual work-around is to make position be an array instead, then it'll all work