I'd like to invoke a function pointer which itself takes a trait object as an argument:
fn invoke(x: &Fn(&WithFoo), y: &MyStruct) {
// MyStruct implements WithFoo
x(y);
}
So far so good. Now, what I'm having trouble with is how to call this with a function pointer with signature such as &Fn(&WithFooBar)
where the trait WithFooBar
inherits from WithFoo
.
Here is my sample code where I attempt to do this:
trait WithFoo {
fn foo(&self);
}
trait WithFooBar: WithFoo {
fn bar(&self);
}
struct MyStruct {
}
impl WithFoo for MyStruct {
fn foo(&self) {
println!("foo");
}
}
impl WithFooBar for MyStruct {
fn bar(&self) {
println!("bar");
}
}
fn foobar_caller(wf: &WithFooBar) {
wf.foo();
wf.bar();
}
fn invoke(x: &Fn(&WithFoo), y: &MyStruct) {
x(y);
}
fn main() {
let data = MyStruct {};
invoke(&foobar_caller,&data);
}
This fails with the following compile error:
error: type mismatch: the type `fn(&WithFooBar) {foobar_caller}` implements the trait `for<'r> std::ops::Fn<(&'r WithFooBar + 'r,)>`, but the trait `for<'r> std::ops::Fn<(&'r WithFoo + 'r,)>` is required (expected trait `WithFoo`, found trait `WithFooBar`) [--explain E0281]
I understand that the error is saying that &Fn(&WithFooBar)
is not &Fn(&WithFoo)
, but given that the WithFooBar
trait inherits from WithFoo
, is seems like it should be possible to pass a pointer to this function.
Is it possible to somehow "downcast" the function pointer to type &Fn(&WithFoo)
? I have tried both this:
let f = &foobar_caller as &Fn(&WithFoo);
invoke(f,&data);
and this:
let f: &Fn(&WithFoo) = &foobar_caller;
invoke(f,&data);
But neither of these attempts works.
(This example is on the rust playground here.)