Search code examples
functionrustclosurestraitstrait-objects

function pointer vs Fn trait object


fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { // definition
    f(arg) + f(arg)
}

do_twice(|x| x + 1, 5) // call

This function accepts both, closures and function pointers. It takes a function pointer as parameter type.

When should I prefer this over using a trait object, like &dyn Fn(i32) -> i32 or Box<dyn Fn(i32)-> i32> instead of fn

fn do_twice(f: &dyn Fn(i32) -> i32, arg: i32) -> i32 { // definition
    f(arg) + f(arg)
}

do_twice(&|x| x + 1, 5) // call

or

fn do_twice(f: Box<dyn Fn(i32) -> i32>, arg: i32) -> i32 { // definition
    f(arg) + f(arg)
}

Solution

  • 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