(now of course an automatic transformation into a structure-of-arrays would be pretty cool, I actually wonder what Zig's MultiArrayList does with tagged unions).
PS: in general I agree though, for instance in Typescript they are fantastic, but there I usually don't care much about memory layout and performance.
Some of that could probably be solved with comptime code (like Zig's MultiArrayList container I mentioned above).
Such as ?
I also wasn't thinking about moving parts of a struct out into heap allocations, I think in most situations that would be worse than having to deal with padding. Instead at least have the programmer think about how the internal memory layout of sum types might affect performance in specific situations instead of just using them everywhere and in mass because they are convenient.
And if the type has some illegal values, these can sometimes be used to discriminate the type. When that's possible, the union will have the same size as the largest underlying type with no overhead for a tag. For example Option<&T> matches the size of &T, since it uses the illegal null value to represent None.
The tag can often be stored inline in the data, so doesn't necessarily require extra space.
> because they always take up as much space as the largest wrapped type
Yeah... but what's the alternative?
enum Foo {
Bar,
Qux([i32; 1024]),
}
as if the user had written enum Foo {
Bar,
Qux(Box<[i32; 1024]>),
}
I don't think it's a good idea to do that kind of silent transformation, instead teach the developer about their options. That way the application's performance doesn't suddenly shift after changing a few parts of unrelated code that accidentally causes some threshold to be crossed that changes the performance characteristics of binary being produced.Today, clippy does what I think is the right thing: it teaches the user
warning: large size difference between variants
--> src/main.rs:1:1
|
1 | / enum Foo {
2 | | Bar,
| | --- the second-largest variant carries no data at all
3 | | Qux([i32; 1024]),
| | ---------------- the largest variant contains at least 4096 bytes
4 | | }
| |_^ the entire enum is at least 4100 bytes
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
= note: `#[warn(clippy::large_enum_variant)]` on by default
help: consider boxing the large fields to reduce the total size of the enum
|
3 | Qux(Box<[i32; 1024]>),
| ~~~~~~~~~~~~~~~~