Here is a simplified example of my problem:

struct User;
struct Community;

enum Actor {
    User(User),
    Community(Community),
}

trait Name {
    fn name() -> &'static str;
}

impl Name for User {
    fn name() -> &'static str { "/u/nutomic" }
}

impl Name for Community {
    fn name() -> &'static str { "/c/rust " }
}

fn main() {
    let actor = Actor::Community(Community);
    println!("{}", actor.name());
}

Playground link

As you may have noticed, this doesnt compile. The only solution I can think of is with a match. I want to avoid that because I have an enum with 30+ variants, and a trait with multiple methods. So that would be a huge match statement in each method, when the compiler should know that the enum variants all have the same trait.

So, do you know any way to make this work without match?

  • Ephera
    link
    fedilink
    arrow-up
    2
    ·
    3 years ago

    Hmm, best I can think of is switching to a whole different paradigm, akin to the Entity-Component-System architecture, but that is a pretty big step and you give up lots of compile time guarantees. So, unless you need lots of flexibility anyways, it’s probably not worth it.

    Here’s a rough example thrown together from code I had laying around: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e91ae7eeff8b79e9e37c7e7917bda5c6

    • nutomicOPMA
      link
      fedilink
      arrow-up
      2
      ·
      3 years ago

      Thanks, but the compile time guarantees are exactly why I want to use this pattern. And honestly your code looks much more complicated than the other option, which is using a macro to generate the match.

    • Ephera
      link
      fedilink
      arrow-up
      1
      ·
      3 years ago

      I guess, this isn’t really directly a solution to your issue, it just kind of feels like an ECS-like solution might be appropriate to obsolete these types of problems completely.

      But yeah, I don’t know your code and as I said, an ECS architecture can really be a pain, too.