我在将特征向量转换为不同特征向量时遇到问题。
使用Type-casting arrays/vectors in Rust的方法,我基本上尝试了以下方法:
trait ParentTrait {}
trait ChildTrait: ParentTrait {}
fn main() {
let mut children: Vec<Box<ChildTrait>> = vec![];
let parents = children.iter().map(|&e| e as Box<ParentTrait>);
}
现在,它不编译,结果是
error: the trait `core::kinds::Sized` is not implemented for the type `ChildTrait`
[...]
error: the trait `ParentTrait` is not implemented for the type `ChildTrait`
[...]
(第二条错误线是编译器的错误行为,我猜是吗?)
我尝试了其他各种引用/框样式,但无法使其正常工作。
我在这儿做错了什么
使用较新版本的 rust (0.13)还是正确的方法吗?
最佳答案
特性对象是非常奇怪的野兽。
什么是Box<ChildTrait>
? Box<T>
实际上是*mut T
的包装。因此,Box<ChildTrait>
包装了*mut ChildTrait
。因为ChildTrait
命名一个特征,所以ChildTrait
是object type。指向对象类型的指针由一对指针表示:指向该特性且仅该特性的vtable的指针,以及指向实际值的指针。
当我们从另一个特征继承一个特征时,这并不意味着我们可以从指向第二个特征的vtable的指针中获得指向第一个特征的vtable的指针。这就是为什么编译器提示
the trait `ParentTrait` is not implemented for the type `ChildTrait`
但是,我们可以手动实现对象类型的特征。因为对象类型是无尺寸的,所以我们必须首先允许为无尺寸的类型实现
ParentTrait
:trait ParentTrait for Sized? {}
然后,我们可以为
impl
对象类型提供ParentTrait
的ChildTrait
:impl<'a> ParentTrait for ChildTrait+'a {}
如果我们现在尝试进行编译,则会遇到不同的错误:
<anon>:9:40: 9:42 error: cannot move out of dereference of `&`-pointer
<anon>:9 let parents = children.iter().map(|&e| e as Box<ParentTrait>);
^~
<anon>:9:41: 9:42 note: attempting to move value to here
<anon>:9 let parents = children.iter().map(|&e| e as Box<ParentTrait>);
^
<anon>:9:41: 9:42 help: to prevent the move, use `ref e` or `ref mut e` to capture value by reference
<anon>:9 let parents = children.iter().map(|&e| e as Box<ParentTrait>);
我们可以使用
into_iter
而不是iter
来消耗初始的Vec
:fn main() {
let mut children: Vec<Box<ChildTrait>> = vec![];
let parents = children.into_iter().map(|e| e as Box<ParentTrait>);
}
但是,然后我们得到一个内部编译器错误:
error: internal compiler error: trying to take the sizing type of ChildTrait, an unsized type
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html
note: run with `RUST_BACKTRACE=1` for a backtrace
task 'rustc' panicked at 'Box<Any>', /build/rust-git/src/rust/src/libsyntax/diagnostic.rs:175
此代码也会发生相同的错误:
fn main() {
let mut children: Vec<Box<ChildTrait>> = vec![];
let parents = children.iter().map(|e| &**e as &ParentTrait);
}
在这一点上,我不知道在修复ICE之后,该编译是否成功。