4 ms·
The thing that's really missing for me in rust is a better way to modularize enums with associated data and their behaviour. There are many cases where you have
by j-pb 4y ago
The thing that's really missing for me in rust is a better way to modularize enums with associated data and their behaviour.
There are many cases where you have a closed set of known variants for a type, but they have very different behaviour, e.g. nodes in any kind of adaptive tree data-structure, such as an ART, HOT or Judy Array.
In those cases you don't want to bring out the big guns with dyn traits. But the current approach involving huge match forests, macros, helper functions and code duplication
plainly sucks ^^'.
This could be solved by making enum variants proper types.
Something that has been proposed already, but which has been rejected due to lacking capacity.
https://github.com/rust-lang/lang-team/issues/122 https://github.com/rust-lang/lang-team/issues/122
- insanitybit 4y agoI've found that the `syn` approach works well here. You just use their Visitor or implement custom Visitors. But yeah, typed enums would be cool. I imagine as more const work is done typed enums will eventually be a natural next step.
- brundolf 4y agoThis does need to be solved, but I came up with a pattern in a recent project I'm pretty happy with: - Create all the variants as normal structs - Create enums around different subsets of them that just wrap each struct in a variant of the same name (including from/tryfrom impls) - Have methods for "casting" one of these enums into another The second and third points can be made fairly non-painful with a macro where you just say "enum X can be structs Y, Z, A, B..." and it creates the variants and impls all the traits for you But yeah. This is one of the bigger pain-points to implementing certain stuff in Rust Edit: just realized you were talking about something slightly different from me, but I think you could extend this pattern to get it: Have a trait that all variants implement, implement it on the enum too, and have the enum delegate to the variant structs (since those are already separate). The wiring should be automatable with the same macro
- j-pb 4y agoThe 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.