我在将特征向量转换为不同特征向量时遇到问题。

使用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命名一个特征,所以ChildTraitobject type。指向对象类型的指针由一对指针表示:指向该特性且仅该特性的vtable的指针,以及指向实际值的指针。

当我们从另一个特征继承一个特征时,这并不意味着我们可以从指向第二个特征的vtable的指针中获得指向第一个特征的vtable的指针。这就是为什么编译器提示

the trait `ParentTrait` is not implemented for the type `ChildTrait`

但是,我们可以手动实现对象类型的特征。因为对象类型是无尺寸的,所以我们必须首先允许为无尺寸的类型实现ParentTrait:
trait ParentTrait for Sized? {}

然后,我们可以为impl对象类型提供ParentTraitChildTrait:
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之后,该编译是否成功。

09-27 09:18