Traits that have Sized as a supertype aren't "object safe" which means dynamic dispatch using dyn isn't possible on these kinds of traits.
You can accomplish this relatively tersely by using an enum for each possible type you want to handle, combined with a macro that will neatly generate all the match arms required to dynamically dispatch on each enum possibility.
To make things simple for the sake of this explanation, I'm going to define a new trait (with the Sized supertype) so that this answer doesn't depend on a particular crate:
trait SampleTrait: Sized {
fn method_a(&self, foo: &str);
fn method_b(&self, foo: i32, bar: String) -> String;
}
Now we need at least two implementations of this trait to demonstrate the solution:
struct ImplA;
struct ImplB;
impl SampleTrait for ImplA {
fn method_a(&self, foo: &str) {
println!("<ImplA as SampleTrait>::method_a(): {:?}", foo);
}
fn method_b(&self, foo: i32, bar: String) -> String {
println!("<ImplA as SampleTrait>::method_b(): {:?} {:?}", foo, bar);
format!("from ImplA: {}", bar)
}
}
impl SampleTrait for ImplB {
fn method_a(&self, foo: &str) {
println!("<ImplB as SampleTrait>::method_a(): {:?}", foo);
}
fn method_b(&self, foo: i32, bar: String) -> String {
println!("<ImplB as SampleTrait>::method_b(): {:?} {:?}", foo, bar);
format!("from ImplB: {}", bar)
}
}
The enum just needs to least each possible type that you need to handle:
enum DynSampleTrait {
ImplA(ImplA),
ImplB(ImplB),
}
Now to dispatch on this, you'd have to do something like:
match value {
DynSampleTrait::ImplA(v) => v.method_a("something"),
DynSampleTrait::ImplB(v) => v.method_a("something"),
}
To get around having to repeat ourselves, let's declare a macro that will generate the whole match for us:
macro_rules! dyn_sample_trait_call {
(($m:expr) $v:ident => $code:block) => {
match $m {
DynSampleTrait::ImplA($v) => $code,
DynSampleTrait::ImplB($v) => $code,
}
}
}
Now we can use the macro like so:
dyn_sample_trait_call!((value) v => { v.method_a("something") })
value goes in the match expression, and v is the identifier that unwraps the inner value held by the enum possibility. These are separate so that you can match over a reference, should you not want to consume an owned DynSampleTrait:
dyn_sample_trait_call!((&value) v => { v.method_a("something") })
(Playground)