I have a problem casting a vector of traits into a vector of different traits.
Using the approach of Type-casting arrays/vectors in Rust , I basically tried the following:
trait ParentTrait {}
trait ChildTrait: ParentTrait {}
fn main() {
let mut children: Vec<Box<ChildTrait>> = vec![];
let parents = children.iter().map(|&e| e as Box<ParentTrait>);
}
Now this does not compile, it results in
error: the trait `core::kinds::Sized` is not implemented for the type `ChildTrait`
[...]
error: the trait `ParentTrait` is not implemented for the type `ChildTrait`
[...]
(The second errorline is buggy behaviour of the compiler, I guess?)
I tried various other flavors of References / Boxes and could not get it to work.
What am I doing wrong here, is this even the correct approach with newer versions of rust (0.13)?
Trait objects are very strange beasts.
What is a
Box<ChildTrait>
?Box<T>
is literally a wrapper for a*mut T
. Therefore, aBox<ChildTrait>
wraps a*mut ChildTrait
. BecauseChildTrait
names a trait,ChildTrait
is an object type. A pointer to an object type is represented by a pair of pointers: a pointer to the vtable for that trait and only that trait, and a pointer to the actual value.When we inherit a trait from another trait, that doesn't mean we can obtain a pointer to the vtable for the first trait from a pointer to the vtable for the second trait. This is why the compiler complains that
We can, however, manually implement a trait for an object type. Because object types are unsized, we must first allow
ParentTrait
to be implemented for unsized types:Then we can provide an
impl
ofParentTrait
for theChildTrait
object type:If we try to compile now, we get different errors:
We can use
into_iter
instead ofiter
to consume the initialVec
:But then we get an internal compiler error:
The same error also occurs with this code:
At this point, I don't know if, after fixing the ICE, this would compile successfully or not.