闭包矢量的推断类型是什么?

VRW*_*VRW 6 rust

我试图创建闭包矢量:

fn main() {
    let mut vec = Vec::new();

    vec.push(Box::new(|| 10));
    vec.push(Box::new(|| 20));

    println!("{}", vec[0]());
    println!("{}", vec[1]());
}
Run Code Online (Sandbox Code Playgroud)

这产生了以下错误报告:

error[E0308]: mismatched types
 --> src/main.rs:5:23
  |
5 |     vec.push(Box::new(|| 20));
  |                       ^^^^^ expected closure, found a different closure
  |
  = note: expected type `[closure@src/main.rs:4:23: 4:28]`
             found type `[closure@src/main.rs:5:23: 5:28]`
  = note: no two closures, even if identical, have the same type
  = help: consider boxing your closure and/or using it as a trait object
Run Code Online (Sandbox Code Playgroud)

我通过明确指定类型来修复它:

let mut vec: Vec<Box<Fn() -> i32>> = Vec::new();
Run Code Online (Sandbox Code Playgroud)

什么是推断类型,vec为什么会这样?

She*_*ter 5

每个闭包都有一个自动生成的唯一匿名类型。将第一个闭包添加到向量后,即向量中所有项目的类型。但是,当您尝试添加第二个闭包时,它具有不同的自动生成的,唯一的匿名类型,因此您将列出错误。

闭包本质struct上是由实现特征之一的编译器创建的Fn*struct闭包捕获的所有变量的contains字段,因此根据定义,它必须是唯一的,因为每个闭包将捕获不同数量和类型的变量。

为什么不能只是推断Box<Fn() -> i32>呢?

“不能”是一个很难回答的问题。这是可能的,编译器可以通过使用的每一种,看一些路口导致代码编译类型的所有特征重复,但感觉有点不可思议给我。您可以尝试打开功能请求或在一个论坛上进行讨论,以查看是否普遍接受这种想法。

但是,Rust确实试图使事情变得明确,尤其是可能涉及性能的事情。当您从具体结构转到特征对象时,您将引入间接访问,这可能会变慢。

现在,Fn*特征与用户构造的特征相同:

trait MyTrait {
    fn hello(&self) {}
}

struct MyStruct1;
impl MyTrait for MyStruct1 {}

struct MyStruct2;
impl MyTrait for MyStruct2 {}

fn main() {
    let mut things = vec![];
    things.push(MyStruct1);
    things.push(MyStruct2);
}
Run Code Online (Sandbox Code Playgroud)
trait MyTrait {
    fn hello(&self) {}
}

struct MyStruct1;
impl MyTrait for MyStruct1 {}

struct MyStruct2;
impl MyTrait for MyStruct2 {}

fn main() {
    let mut things = vec![];
    things.push(MyStruct1);
    things.push(MyStruct2);
}
Run Code Online (Sandbox Code Playgroud)