book icon indicating copy to clipboard operation
book copied to clipboard

19.4 Cannot use function pointer as return type

Open maciejzelaszczyk opened this issue 3 years ago • 1 comments

  • [x] I have checked the latest main branch to see if this has already been fixed
  • [x] I have searched existing issues and pull requests for duplicates

URL to the section(s) of the book with this problem: https://github.com/rust-lang/book/blob/main/src/ch19-05-advanced-functions-and-closures.md#returning-closures

Description of the problem:

But you can’t do that with closures because they don’t have a concrete type that is returnable; you’re not allowed to use the function pointer fn as a return type, for example.

However, this compiles rustc 1.58.1 (db9d1b20b 2022-01-20):

fn inner(x: i32) -> i32 {
    x + 1
}

fn function_pointer() -> fn(i32) -> i32 {
    inner
}

fn closure() -> fn(i32) -> i32 {
    |x| x + 1
}

Suggested fix: Rephrase description or get rid of the function pointer mention altogether.

maciejzelaszczyk avatar Feb 11 '22 15:02 maciejzelaszczyk

One can coerce non-capturing closure to a function pointer (just like with lambdas in in C++). However, the following example does not compile, as the closure is now capturing:

fn returns_closure() -> fn(i32) -> i32 {
    let one = 1;
    move |x| x + one
}

More complex example, which won't allow for compiler optimizations:

fn create_adder(to_add: i32) -> fn(i32) -> i32 {
    move |x| x + to_add
}

Still, one can return impl Fn(i32) -> i32, thus propagating the "unknown" type of the capture (I think of it as returning auto in C++):

fn create_adder(to_add: i32) -> impl Fn(i32) -> i32 {
    move |x| x + to_add
}

fn main() {
    println!("2 + 3 = {}", create_adder(3)(2));
}

yeputons avatar Apr 05 '22 14:04 yeputons