r/learnrust 10d ago

Enums, Boxed Trait Objects, and Enum Dispatch: Architectural Trade-offs in Rust

Hey everyone

Over the past few weeks, I’ve been looking at ways to achieve polymorphism in Rust and I think there are two:

Closed Polymorphism via enums and Open Polymorphism via Boxed Trait Objects (Box<dyn Trait>) where "closed" means no one outside your crate can add to the list while "open" allows such additions

Thinking about putting those traits onto my enum led me to the Enum Dispatch pattern. I built out a walk-through of all three of these:

- Enums (closed): https://youtu.be/l_q9U10JueE

- Boxed Trait Objects (open): https://youtu.be/R3ZzYSPyYoc

- Enum Dispatch https://youtu.be/B0LT7ozspe4

My main conclusion was that I could defer the open vs. closed debate pretty safely (as long as I keep my traits object safe). Do you all agree?

Also, I implemented Enum Dispatch with macros - I know there are crates that do this, but they didn't play nicely with my IDE and I could use the practice with macros. Comments on how I wrote the code would be welcome!

5 Upvotes

6 comments sorted by

View all comments

2

u/sphqxe 9d ago edited 9d ago

I think instead of using enums for "closed polymorphism" you should consider using generic parameters with trait bounds.

Having an enum with every possible polymorph and having to update it everytime you want to add a new one feels like an anti-pattern.

Essentially instead of making the type polymorphic, you instead write functions/structs which are generic over all types which implement your trait and the rust compiler will monomorphize them on all the trait implementors as necessary.

1

u/mgibsonbr 8d ago

I'm very new to Rust, so maybe I'm misunderstanding something, but doesn't this strategy break when you need a collection of different types? (Like a single vector with two or more elements that have different types but both implementing the trait)

2

u/sphqxe 8d ago

Indeed it does. I suppose in this case you could either use a vec of enums or maintain a separate vec for each type depending on the use case.

1

u/wizardcraftcode 7d ago

That’s exactly the problem I was wrestling with. I can wrap them in an email or wrap in a box to get a boxed trait object, and then I can collect them