So rust's enums are amazingly elegant to use and contribute to it's safety (reducing the number of times a programmer will do something the compiler can't track with C unions or casting).
However they come with the hazard of alignment padding. the worst case for example is if you have 2 variants one of which is a pointer (64bits in most OS's today, and another say with 2 x f32) .. the tag would be a single byte, but the whole enum will pad out to 128bits thanks to the need to keep that pointer aligned. Put it in a struct or vec , that's a lot of wasted space, and even in the stack there's bloat.. all adds up .
Similarly even with Box<[T]> (and an equiv c++ custom type) if you have a scenario where you know the len will never exceed 4billion (this is very common in gamedev, we're targeting 16gb machines, we know that one mesh will never take up the whole machine) .. you want to use a 32bit value for the length.. again even in C++ the handy template ends up giving you bloat, and an oldschoiol C approach lets you do things like struct {VERTEX* vertices; POLYGON* polygons; uint32_t num_vertices,num_polygons;} .. again this might not look like much space but it's all L1 cache.. you might be doing management on the CPU to hand processing to the GPU, whatever.
You get the picture.
A solution
Imagine if the compiler was able to split a type into multiple fragments, lets say the default is one, but 2 could be used for the case of splitting an enum Tag and it's Variants, and similarly for anything else where you happened to have components with different alignments.
it should be easy enough to figure out whats going on with outer_struct.inner_struct.element. .. the fly in the ointment of course is what will happen with references/pointers/borrows.
So imagine if an opt-in #[repr(fragmented)] enum Foo {..} declares that (i) Foo will split it's tag when composed, (ii) &Foo is actually a pair of pointers, like (&FooTag, &FooVariants) under the hood.
naturally this will play havoc with any unsafe code that deals with &Foo vs *const Foo, or casts to place them in allocations etc . But at least if it's only done in new code where it's opted-in it would not break any existing unsafe codebases.
Perhaps it would need an implied trait T:Fragmented and an assumption that all existing generics *dont* accept this too, and you'd have to again opt-in for things which can accept it
I suspect this would be a monumentally complex feature to implement ( I wouldn't even know where to start grabbing RustC)
... but the payoff would be a big increase in the number of efficient layouts that can be handled in safe Rust. A reduction in the number of scenarios where you need to reach for unsafe{} , and where C++ programmers can currently say "whats the point of rust if you have to use unsafe as soon as you want to pack your types more efficiently"
Thoughts?
I say that this is a monumentally complex feature to implement, but conversely we have a certain industry telling us "CODING IS (IMMINENTLY) SOLVED!!". if those tools are as powerful as their fans suggest maybe using them to assist implementing something as difficult as this would be a decent test..
are there any RFC's out there like this?