Enum with properties


#1

It would be good to let enums to have properties which is fixed (like in a regular structure), here is an example:

enum Tree {
  id: u64,

  Node { left: Box<Tree>, right: Box<Tree> },
  Leaf
}

fn main() {
  let item = Tree::Node { id: 1, left: Box::new(Tree::Leaf { id: 2 }), right: Box::new(Tree::Leaf { id: 2 }) };
  println!("{}", item.id);
}

#2

or may be somehow like this:

struct Tree {
    id: u64,
    value: enum {
        Node(Box<Tree>, Box<Tree>),
        Leaf
    }
}

#3

This syntax feels like I’ve seen it somewhere before… Ah, got it:

http://smallcultfollowing.com/babysteps/blog/2015/08/20/virtual-structs-part-3-bringing-enums-and-structs-together/

Did you get anywhere with that idea since that time, @nikomatsakis ?


#4

This sounds a lot like the problem the compiler team faces when representing a program’s AST in memory.

The current solution is to have some Item struct which holds all the common things in an item (identifier, span, attributes, etc), then it also contains an ItemKind enum to hold data relevant to a particular kind of node (e.g. function declaration, impl block, etc).

I’ve used this pattern in my code and it turns out to be quite powerful. It requires two type definitions instead of the one though…


#5

Yes, I did it the same way, but I found it a bit bulky: everytime you need to create 2 things instead of 1 and destructuring looks like:

if let SomeStruct { some_field: some_var, SomeEnum::SomeVariant(some_variant_var) = some_struct {
  ...
}

#6

Another problem with that is, that one will often end up with a larger enum memory wise, since both items are individually padded. That may be not that important for many, but every time I needed this it was in cases where the overhead was significant.

I often use one enum and duplicate the common fields and access it with a pattern match. But that is not really a satisfying solution either (and i don’t know if its getting optimised properly).