特征对象的 Rust 向量的类型推断不正确
Incorrect type inference for Rust vector of trait object
我无法理解以下错误:
// 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 关于特征对象向量的类型推断的一些缺失 feature/bug?我对 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>>
,因为您告诉编译器这是您想要的类型。
我无法理解以下错误:
// 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 关于特征对象向量的类型推断的一些缺失 feature/bug?我对 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>>
,因为您告诉编译器这是您想要的类型。