Rust 闭包真的不需要类型注解吗?

Do Rust closures really not need type annoations?

我目前正在阅读 Rust 这本书,我刚刚进入主题 closures。 一个让我吃惊的细节是,Rust 书中说

Closures don’t require you to annotate the types of the parameters

我立即对此进行了测试,因为它看起来确实与 Rust 通常的工作方式有悖常理。因此,我复制了 exactly the closure they used,将其粘贴到我的代码中,然后...出现错误:

fn some_closure() {
    let expensive_closure = |num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    };
}
error[E0282]: type annotations needed
  --> src/main.rs:14:30
   |
14 |     let expensive_closure = |num| {
   |                              ^^^ consider giving this closure parameter a type

error: aborting due to previous error

我当然知道那个错误的意思,但我仍然对它感到困惑,因为不仅是书,而且 reference 都指定不需要注释,但我却收到这个错误。

这只是最近的更改,尚未记录在案,还是我误解了什么?

编译器需要能够以某种方式推断出参数的类型,这可以通过 num: i32 中的显式类型注释或

中的上下文信息来实现
fn use_some_closure() {
    let expensive_closure = |num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    };
    expensive_closure(42);
}

如果没有注释或用法,就无法弄清楚 num 是什么。

Playground

the book, but also the reference specify that theres no annotations needed, yet I am getting this error.

不是,书和参考的关键词是required,和needed不同。即使通常不需要,也可以根据上下文需要某些内容。

对于闭包,区别在于“静态函数”(fn),后者的注释是语法要求:如果没有注释,您将无法编写有效的静态函数提供类型注释,而一般来说您可以编写没有类型注释的闭包。

但是编译器仍然需要知道闭包的具体类型,这需要能够推断出参数 & return 类型。如果因为没有足够的约束而不能,它会抱怨并需要明确指定类型。

在你的例子中,num 的类型没有任何限制,所以 rustc 无法知道 numconcrete 类型是什么,因此无法推断闭包的具体类型。

但在大多数情况下,例如

let it = repeat(5).map(|x| x+1);

编译器对此很满意,因为闭包的输入和输出类型必然是 map 提供的,即 Repeat::Item,在本例中是 i32(因为这是整数文字默认禁止其他约束的内容。