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)
}