Prana
Prana

Reputation: 703

Syntax issue function returns function not clear

I'm getting confused by this. If the following works:

fn func_exit() -> bool {
    println!("hi");
    true
}

fn locate_func() -> fn() -> bool {
    func_exit
}

Why these following syntaxes throw error?

fn locate_func1<F: Fn() -> bool>() -> F {
     func_exit
}
fn locate_func2<F>() -> F where F:Fn() -> bool {
    func_exit
}

I'm new to Rust and the following error message is not clear to me:

error[E0308]: mismatched types
  --> src/main.rs:44:9
   |
43 |     fn locate_func1<F: Fn() -> bool>() -> F {
   |                     - this type parameter - expected `F` because of return type
44 |         func_exit
   |         ^^^^^^^^^ expected type parameter `F`, found fn item
   |
   = note: expected type parameter `F`
                     found fn item `fn() -> bool {func_exit}`
   = help: type parameters must be constrained to match other types
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

error[E0308]: mismatched types
  --> src/main.rs:47:9
   |
46 |     fn locate_func2<F>() -> F where F:Fn() -> bool {
   |                     -       - expected `F` because of return type
   |                     |
   |                     this type parameter
47 |         func_exit
   |         ^^^^^^^^^ expected type parameter `F`, found fn item
   |
   = note: expected type parameter `F`
                     found fn item `fn() -> bool {func_exit}`
   = help: type parameters must be constrained to match other types
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

Appreciate some help. Thanks

Upvotes: 0

Views: 74

Answers (2)

Masklinn
Masklinn

Reputation: 42492

The error is weird, but... you can't just return a bounded value like this, because bounded types are decided by the caller, and it doesn't make sense for the caller to decide what the return type is unless that return type is a consequence of an input type (e.g. an identity function is a trivial example of this). Which is not the case here.

If you want to return something generic, you need either some sort of trait object (so e.g. box the function and return a Box) or an impl (which still has a concrete return value but hides it at the API level).

The latter is more efficient but only allows returning a single concrete type, the former is less efficient but lets you return e.g. different closures.

Upvotes: 1

phimuemue
phimuemue

Reputation: 36031

fn locate_func() -> fn() -> bool {
    func_exit
}

locate_func returns a pointer to a function returning bool (i.e. fn() -> bool).

fn locate_func1<F: Fn() -> bool>() -> F {
     func_exit
}

locate_func1 means that the caller can specify any F satisfying the bounds Fn() -> bool, and it will return an F. But it is clearly not the case that func_exit is necessarily of the type specified by the caller.

locate_func2 has the same problem, just with where-Notation.

What you probably want could be the following:

fn locate_func3() -> impl Fn() -> bool {
     func_exit
}

It says: locate_func3 returns something that implements the bound Fn() -> bool (and func_exit does so, so it can be returned there).

Also note the difference between fn (function pointers) and Fn ("something callable"):

Upvotes: 3

Related Questions