10

I started reading the Rust guide on closures. From the guide:

That is because in Rust each closure has its own unique type. So, not only do closures with different signatures have different types, but different closures with the same signature have different types, as well.

Is there a way to explicitly write the type signature of a closure? Is there any compiler flag that expands the type of inferred closure?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
basic_bgnr
  • 697
  • 5
  • 14

2 Answers2

9

No. The real type of a closure is only known to the compiler, and it's not actually that useful to be able to know the concrete type of a given closure. You can specify certain "shapes" that a closure must fit, however:

fn call_it<F>(f: F)
where
    F: Fn(u8) -> u8, // <--- HERE
{
    println!("The result is {}", f(42))
}

fn main() {
    call_it(|a| a + 1);
}

In this case, we say that call_it accepts any type that implements the trait Fn with one argument of type u8 and a return type of u8. Many closures and free functions can implement that trait however.

As of Rust 1.26.0, you can also use the impl Trait syntax to accept or return a closure (or any other trait):

fn make_it() -> impl Fn(u8) -> u8 {
   |a| a + 1
}

fn call_it(f: impl Fn(u8) -> u8) {
    println!("The result is {}", f(42))
}

fn main() {
    call_it(make_it());
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
1

Quoting the reference, "A closure expression produces a closure value with a unique, anonymous type that cannot be written out".

However, under conditions defined by RFC1558, a closure can be coerced to a function pointer.

let trim_lines: fn((usize, &str)) -> (usize, &str) = |(i, line)| (i, line.trim());

Function pointers can be used in .map(), .filter(), etc just like a regular function. Types will be different but the Iterator trait will be present on the returned values.

Dmitrii Demenev
  • 735
  • 1
  • 5
  • 13
  • 1
    This is not true. A function pointer and a closure are not the same. A function pointer can often be coerced to a closure, but not always. Whenever you try to do this with a closure that captures variables that are not `Copy + Clone`, you will find that it throws an error. – CATboardBETA Feb 13 '23 at 18:44
  • @CATboardBETA You can notice that I never claimed that function pointers and closures are the same. However, it's a really good observation that not all closures can be coerced to a function pointer. I'll update my answer to convey the limitations. – Dmitrii Demenev Feb 15 '23 at 08:19