微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

特征对象的 Rust 向量类型推断不正确

如何解决特征对象的 Rust 向量类型推断不正确

我无法理解以下错误

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

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

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

解决方法

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

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

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。