1

How to convert Box in generics to Box.
from Container<Box<Dog>> to Container<Box<dyn Animal>>

//example
fn main() {
  let container: Container<Box<Dog>> = Container(Box::new(Dog()));

  let test: Container<Box<dyn Animal>> = container;
  // expected struct `RcHash<Box<dyn Enity>>`
  // found struct `RcHash<Box<Role>>`

  let test = container as Container<Box<dyn Animal>>;
  // non-primitive cast: `Container<Box<Dog>>` as `Container<Box<dyn Animal>>`
  // an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
}

//struct
struct Container<T> (T);
struct Dog ();

//trait
trait Animal { fn echo(&self); }
impl Animal for Dog { fn echo(&self) { println!("dog"); } }
Xiao_e_yun
  • 188
  • 1
  • 10

1 Answers1

0

You can't do a simple cast between Box<Dog> and Box<dyn Animal>, as they are not quite the same thing. Both Boxes might act as pointers to a Dog instance, but Box<dyn Animal> will actually have a different size, because trait objects also have an extra pointer (for the vtable). I suggest you read this to better understand that part about trait objects.

The above means you can't avoid creating a new Box<dyn Animal> instance, hence you can't avoid creating a new Container<Box<dyn Animal>> instance (because if A != B => Container<A> != Container<B> /here you could interpret != as 'not compatible' or 'of a different size'/).

Here is an example how you can "manually" create a new Box<dyn Animal> instance out of a Box<Dog> instance:

let dog_box: Box<Dog> = Box::new(Dog());
let animal: Box<dyn Animal> = Box::new(*dog_box);

That will essentially move the doggie instance (not create another clone).

And this is the more complete example for your case:

let container: Container<Box<Dog>> = Container(Box::new(Dog()));
let cont_animal: Container<Box<dyn Animal>> = Container(Box::new(*container.0));
at54321
  • 8,726
  • 26
  • 46