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

时间:2015-03-31 15:04:22

标签: rust

我试图创建闭包矢量:

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

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

    println!("{}", vec[0]());
    println!("{}", vec[1]());
}

产生了以下错误报告:

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

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

let mut vec: Vec<Box<Fn() -> i32>> = Vec::new();

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

1 个答案:

答案 0 :(得分:5)

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

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

  

为什么它只能推断Box<Fn() -> i32>

&#34;可以&#39; T&#34;这是一个难以回答的问题。它可能编译器可以遍历每个类型的所有特征,用于查看某个交集是否导致代码编译,但这对我来说有点神奇。您可以尝试打开功能请求或在其中一个论坛上讨论它,看看是否普遍接受这样的想法。

然而,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);
}
error[E0308]: mismatched types
  --> src/main.rs:14:17
   |
14 |     things.push(MyStruct2);
   |                 ^^^^^^^^^ expected struct `MyStruct1`, found struct `MyStruct2`
   |
   = note: expected type `MyStruct1`
              found type `MyStruct2`