Inconsistent type inference of closure arguments

⚓ Rust    📅 2025-12-05    👤 surdeus    👁️ 1      

surdeus

I am trying to create a callback API, and have problems with closure type inference.

In this example type inference works:

fn main() {
    let f = |t| t + 1.;
    assert_eq!(f(0.), 1.); 

    let f = |t| f64::cos(t);
    assert_eq!(f(0.), 1.);
}

But the following example, despite being similar, does not compile:

fn main() {
    let f = |t| t.cos();
    assert_eq!(f(0.), 1.);
}

The error is

error[E0282]: type annotations needed
   |
   |     let f = |t| t.cos();
   |              ^  - type must be known at this point
   |
help: consider giving this closure parameter an explicit type
   |
   |     let f = |t: /* Type */| t.cos();
   |               

And indeed, adding type annotations fixes it:

fn main() {
    let f = |t: f64| t.cos(); // type annotation added
    assert_eq!(f(0.), 1.);
}

Similar behavior is observed, when type inference is provided not by calling a closure directly, but by passing it to other function that accepts impl Fn(f64) -> f64 as an argument. For more elaborate examples, see code at Rust Playground.

The other case I found, is that unary minus is also preventing type inference (see also similar issue Inconsistent type inference in closures which had no response). The behavior of unary minus makes the following example look ridiculous:

let f = |t: f64| -t + 1.; // type annotations required
assert_eq!(f(2.), -1.);

// let f = |t| -t + 1.; // doesn't compile without type annotations
// assert_eq!(f(2.), -1.);

let f = |t| 1. - t; // works fine
assert_eq!(f(2.), -1.);

This behavior confuses me. Why inference works when Add, Mul, Sub, Div operations are used, but breaks with Neg? Why inference works with qualified f64 methods, like f64::exp(t), f64::sin(t), or f64::powi(t, 2), etc, but it breaks with usual dot notation like t.exp(), t.sin(), or t.powi(2). To me it looks like a bug in compiler, but I am not competent to justify that opinion.

2 posts - 2 participants

Read full topic

🏷️ Rust_feed