2014-11-22 29 views
1

我有一个问题,将特质矢量转换成不同特质的矢量。铁锈矢量特性:铸造每个特质

使用的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` 
[...] 

(第二errorline是编译器的错误行为,我猜?)

我试过各种其他口味的参考文献/盒,并不能得到它的工作。

我在做什么错在这里, 这是更新版本的锈(0.13)的正确方法吗?

回答

1

特征对象是非常奇怪的野兽。

什么是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? {} 

然后,我们可以为ChildTrait对象类型提供的ParentTraitimpl

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之后,它是否会成功编译。

+0

谢谢你的解释!你知道这是一个已知的错误吗?否则我会提交一个新的bug报告。 – LinuCC 2014-11-22 15:05:04

+0

证实目前不可能通过这种方式施加特征,但应该在将来进行。 – LinuCC 2014-11-23 18:06:11