function pointer vs Fn trait object
fn
type is a bare function pointer (https://doc.rust-lang.org/std/primitive.fn.html).
It won't work with the closure that captures environment and it cannot be implemented manually for your fancy type (like impl Fn for MySuperType
)
So the only reason why your examples working is the fact that it's oversimplified!
if you make it just a bit more complicated, it will fail https://gist.github.com/rust-play/2167e73325daa1e2a179505209405917
When should I prefer this over using a trait object
Trait objects are not the only other option. As @DarthKotik pointed out, accepting a fn
pointer will not permit closures that capture their environment, but you can just use a normal type parameter, bounded by Fn
to accept both functions and closures, without needing to box anything:
fn do_twice<F>(f: F, arg: i32) -> i32
where
F: Fn(i32) -> i32
{
f(arg) + f(arg)
}
Or, equivalently, but avoiding an extra type variable:
fn do_twice(f: impl Fn(i32) -> i32, arg: i32) -> i32 {
f(arg) + f(arg)
}