I'm wondering if there is a reference for the current layout rules for structs and enums? I know it's not set in stone and that it recently changed, but it'd be nice to be able to predict how large a data structure will be.
I think it's a stable descending sort by alignment for structs, and ascending for enums so the tag can stay small.
And does the tag always come at the beginning of an enum?
It sounds like the tag is then maximal if you have an enum distinguishing between struct types?
Yes, the tag is at the beginning because it has to be in the same place for all variants, and those might be wildly different sizes. Maybe it could be at the end of the largest, and apply lots of padding in smaller variants, but for now it's simplest to put the tag first.
Maybe the tag could be put that the end when all the variants are the same size and doing so will reduce the size of the enum? That would be a relatively conservative change that would enable those who care about size to get more compact data structures while maintain the flexibility of using structs as fields within the enum so as to be able to reuse code for related enums.
Actually, I don't think beginning or end would make a difference for the tag, because it's always wholly outside of the individual fields. The assumption is that anyone with a &mut T
could write the entire size_of::<T>()
, so we don't want that to clobber the tag. Thus it can't use inner padding.
e.g. enum FooBar { Foo, Bar(u16, u8) }
is 4 bytes; enum FooBar { Foo, Bar((u16, u8)) }
is 6 bytes. (I think... didn't verify.)
Even in the case of a 12 byte struct aligned on an 8 byte boundary the tag couldn't be placed in the remaining 4 bytes?
struct InnerA(u64, u32);
struct InnerB(u32, u32, u32);
enum Wrapper {
A(InnerA), B(InnerB),
}
It'd be nice for wrapper to fit in 16 bytes, and I don't understand how it'd be a problem.
But because of that alignment, size_of::<InnerA>()
is 16, not 12.
I see, I hadn't realized that structs were padded to match their alignment.
You might like reading through these ideas for enums:
https://github.com/rust-lang/rfcs/issues/1230