2014-11-22 70 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