6 ms·
The issue with the enum of structs approach is that it doesn't really work for low-level stuff with lots of byte-packing. Compare the following #[repr(u8)]
by j-pb 4y ago
The issue with the enum of structs approach is that it doesn't really work for low-level stuff with lots of byte-packing.
Compare the following
#[repr(u8)]
enum Dense {
A {
foo: u8,
bar: u16,
}
}
struct AStruct {
foo: u8,
bar: u16,
}
#[repr(u8)]
enum Padded {
A {
inner: AStruct
}
}
The Dense enum will be 4byte, because Rust will use the u8 tag as an implicit first field of a tagged union with all the variants fields.
However Padded will be 6 bytes, because AStruct is padded to 4byte, as the u16 causes it to have 2 byte alignment.
That two byte alignment causes it then to be padded again when combined with the u8 tag.
You can't mark AStruct as #[repr(packed)] either, because then the compiler can't proof that the struct will never be moved out of it's alignment providing variant (and unaligned field access is a no no for rust).
The only other thing I could think of would be to transmute between the structs representing the variants, but I think that will probably cause UB because it destroys an ungodly amount of providence information.
- brundolf 4y agoYeah, makes sense. I'm fortunate that my use-case doesn't have to worry about that In general, coming from TypeScript I'd like to see a lot more "duck" types in Rust that describe shapes the compiler already knows how to deal with, just placing additional constraints on what the user can do with them. Individual enum variants, but also subsets of a given enum (where the representation can still just be the same as the full enum) Along similar lines, I'd really really like "anonymous structs" (basically tuples with named members). That seems especially low-hanging since tuples already exist; it's almost just sugar I think there's a lot you could do here that would fit really neatly into Rust's existing type system, but like in the RFC above I assume it's just a matter of devs not having time to implement it all
- zozbot234 4y agoThe problem then is what should happen if you define two "anonymous structs" that share some members (name and type). Most users want these to be seamlessly extensible, which amounts to full row types as seen in OCaml.
- brundolf 4y agoIt would be nice if subset-structs worked like they do in TypeScript, but I would still be totally happy if they had to be an exact match. Subset matching would probably be the 80% complexity for the 20% benefit Now... a neat compromise could be something like this fn foo<T: { bar: i32 }>(my_struct: T) { } foo({ bar: 12, stuff: "abc" }) That would fit a lot more smoothly into Rust's type system than the automatic subset-matching would, but even then, I'd be content without it. The most basic version of anonymous structs is hardly more than sugar over tuples, it just seems like such an easy win