Rust 特征对象锈向量的错误类型推断

Rust 特征对象锈向量的错误类型推断,rust,trait-objects,Rust,Trait Objects,我无法理解以下错误: // test.rs struct A { a: u32 } trait B { } impl B for A { } struct C { c: Vec<Box<dyn B>>, } fn test() { let a = A {a: 1}; let a_vec = vec![Box::new(a)]; let c = C { c: a_vec, // c: vec!

我无法理解以下错误:

// test.rs

struct A {
    a: u32
}

trait B { }

impl B for A { }

struct C {
    c: Vec<Box<dyn B>>,
}

fn test() {
    let a = A {a: 1};
    let a_vec = vec![Box::new(a)];
    let c = C {
        c: a_vec,
        // c: vec![Box::new(a)],
    };
}
错误发生在我试图创建C的那一行。有趣的是,如果我用下面的方法创建C,那么它就可以编译了

let c = C {
        c: vec![Box::new(a)],
    };
另一种可行的方法是

let a_vec: Vec<Box<dyn B>> = vec![Box::new(a)];
let c = C {
        c: a_vec,
    };
让a_vec:vec=vec![框:新(a)];
设c=c{
c:a_vec,
};
我做的另一个实验是将C.C的类型改为Box而不是Vec,然后不管我如何启动它,它都会编译


在我看来,这可能是Rust关于特征对象向量的类型推断中缺少的一些特性/缺陷?我还是个新手,所以对此有任何想法都非常感谢

这都是预期的行为。一个
框,只要编译器知道目标类型是
Box
,它就会隐式发生。但是,刚写的时候,

let a_vec = vec![Box::new(a)];
编译器不知道向量的项类型,因此它从右侧的表达式推断,这意味着
a_vec
以类型
vec
结束

不存在从
Vec
Vec
的未调整大小的强制。将
Box
转换为
Box
仅仅意味着将指针转换为堆栈上的胖指针,这是一种廉价的操作。转换这些元素的向量是非常不同的–它需要重新分配整个向量并取消每个元素的大小,这是一个相当昂贵的操作,因此它永远不会隐式发生


在所有实际编译的版本中,向量从一开始就被创建为
Vec
,因为您告诉编译器这是您想要的类型。

另一个有效的变体是
Vec![框::新(a)为33;]
。错误本身是由于细指针(盒装混凝土结构)和胖指针(盒装dyn特性)之间的差异造成的。一个可以转换为另一个(前提是结构实现了trait),但有时编译器需要一些轻推来执行转换。这是一个好问题,无论是类型推断中的缺陷还是某个更深层次原则的结果。这都是预期的行为-我不期望的部分是针对
vec![Box::new(a)]
不起作用,但适用于
vec![Box::new(a)as quot]
开始工作。
as
看起来是多余的-它给了编译器哪些没有它就无法推断的新信息?@user4815162342从某种意义上说,它实际上给了编译器更少的信息。编译器试图根据右侧推断
a_vec
的类型。如果右侧为
vec![Box::new(a)]
,编译器可以推断出完整的类型,
Vec
,因为这是表达式的类型。如果将
添加为
,编译器将无法再推断完整的类型,而只能推断
Vec
。初始化
c
之后,编译器会进一步提示
实际上是
Box
。谢谢。我试图理解为什么编译器会推断出
let a_vec=vec的向量的完整类型![Box::new(a);/*在需要vec的地方使用_vec*/
,但不要在
中让c=c{c:vec![Box::new(a)]}
。我预计如果前者由于类型不匹配而无法编译,后者也会如此。或者,换句话说,如果为编译OP的代码而更改了编译器,在某些情况下会导致问题吗?@user4815162342 in
let c=c{c:vec![Box::new(a)]
,没有可推断的类型。结构
c
c
字段的类型已经已知。
let a_vec = vec![Box::new(a)];