Rust closure unable to compile

I'm reading the book rust authoritative guide. When I see the closure chapter, why can't the following code be compiled

fn main() {
    let x_closure = |x| x + 2;
}

The book says that closures can be inferred automatically without defining data types

What is the type of the closure's x parameter? Without an annotation (e.g. |x: u32| ...) it's ambiguous, because there are a large number of types which would make the expression, x+2, valid.

This is an error message

type annotations needed

consider giving this closure parameter a typerustc(E0282)
main.rs(2, 22): consider giving this closure parameter a type
fn add_one (x: u32) -> u32 { x +1 }
let add_one_v2 = |x: u32| -> u32 { x+1 };
let add_one_v3 = |x| { x+1 };
let add_one_v4 = |x| x+1;

For rustc to correctly infer the type of the closure's argument, the closure must actually be used somewhere. For example, this program compiles, since the closure is inferred to be a Fn(i32) -> i32:

fn main() {
    let x_closure = |x| x + 2;
    println!("{}", x_closure(3));
}

And this program compiles, since the closure is inferred to be a Fn(&i32) -> i32:

fn main() {
    let x_closure = |x| x + 2;
    println!("{}", x_closure(&3));
}

But this does not compile, since the closure is inferred to be a Fn(i32) -> i32 and cannot accept an &i32:

fn main() {
    let x_closure = |x| x + 2;
    println!("{}", x_closure(3));
    println!("{}", x_closure(&3));
    // mismatched types: expected integer, found `&{integer}`
}

So there's really three sources from which closure parameters' types can be determined:

  1. By their usage when the closure is called (or passed to another function)
  2. By their usage within the closure
  3. By explicit type annotations on the parameters

In your example, none of the three sources specify the type of x. The compiler knows that the type of x must implement Add<{integer}> for a certain {integer} type, but it cannot work backward to determine the exact type. This is why it gives an error.

4 Likes

thanks