2

我无法理解以下错误:

// 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)],
    };
}

编译错误:

mismatched types

expected trait object `dyn test::B`, found struct `test::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,
    };

我做的另一个实验是将 Cc 的类型更改为 Box 而不是 Vec<Box>,然后无论我如何启动它都会编译。

在我看来,这可能是 Rust 关于特征对象向量的类型推断的一些缺失功能/错误?我对 Rust 还是很陌生,所以对此的任何想法都非常感谢!

4

1 回答 1

0

这都是预期的行为。Box<A>可以将A强制转换为 a Box<dyn B>- 这称为unsized coercion,只要编译器知道目标类型是 ,它就会隐式发生Box<dyn B>。但是,刚写的时候

let a_vec = vec![Box::new(a)];

编译器不知道向量的项目类型,因此它从右侧的表达式推断它,这意味着a_vec以 type 结尾Vec<Box<A>>

Vec<Box<A>>从to没有大小不一的强制Vec<Box<dyn B>>。转换Box<A>Box<dyn B>简单意味着将指针转换为堆栈上的胖指针,这是一种廉价的操作。转换这些元素的向量是非常不同的——它需要重新分配整个向量并取消每个元素的大小,这是一个相当昂贵的操作,所以它不应该隐式发生。

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

于 2021-04-01T09:49:25.983 回答