structmatchmatchingrusttraits

How do you match a trait in rust?


Let's say I have the structs F1 and F2 that implement the trait Foo.
Now I want to write a function that accepts Foo and returns Bar.

trait Foo {
    fn get_bar(&self) -> &Bar
}
fn do_match(f: &Foo) -> &Bar {
    &match *f {
       F1 => { f.get_bar() } // Error: mismatched types: expected `Foo`, found an enum or structure pattern
       F2 => { f.get_bar().modify_somehow(3f64) }
    }
}

Is it possible to match against structs implementing the trait Foo?


Solution

  • No, match cannot match on the concrete type of a value. Considering that match requires the patterns to be exhaustive, and that traits are open (types from other modules or other crates can implement your trait), you could never cover all cases (unless you have a simple variable binding like x on the last arm). match works better on enums, which are closed (the set of variants is fixed in the enum's definition).

    You can introduce a second trait to do dynamic dispatch. Note that you can define the second trait and its implementations in a different module or a different crate from where F1 and F2 are defined.

    trait Foo2 {
        fn get_bar2(&self) -> &Bar;
    }
    
    impl Foo2 for F1 {
        fn get_bar2(&self) -> &Bar {
            self.get_bar()
        }
    }
    
    impl Foo2 for F2 {
        fn get_bar2(&self) -> &Bar {
            self.get_bar().modify_somehow(3f64)
        }
    }
    
    fn do_match(f: &Foo2) -> &Bar {
        f.get_bar2()
    }