Passing Obj in place of Trait

#1
  1. I have code that reduces ot the following:

pub trait AnimalT {
    fn num_legs(&self) -> isize;
}


pub struct Cat {}

impl AnimalT for Cat {
    fn num_legs(&self) -> isize { unimplemented!() }
}

pub struct Wrapper<'a, T: ?Sized> {
    pub animal: &'a T,
}

pub fn foo<'a>(animal: Wrapper<'a, AnimalT>) {
}

#[test]
fn test() {
    let c = Cat{};
    let f: Wrapper<Cat> = Wrapper{ animal: &c };
    foo(f);

}
  1. I get the error of:
   |
26 |     foo(f);
   |         ^ expected trait AnimalT, found struct `Cat`
   |
   = note: expected type `Wrapper<'_, (dyn AnimalT + 'static)>`
              found type `Wrapper<'_, Cat>`
  1. This is confusing to me because we have impl AnimalT for Cat so I see no reason why a &'a AnimalT can not store a &'a Cat

  2. What am I doing wrong, and how do we fix this?

0 Likes

#2

Rust will only implicitly convert a value to a trait object in some situations. It won’t in this situation, so you have to explicitly do it:

let f = Wrapper { animal: &c as &dyn AnimalT };
1 Like

#3

Here’s a working example
Notice that I have essentially changed the contents of Wrapper from dyn AnimalT to T: AnimalT, so that it can be resolved by the type checker. As @arthrowpod points out, it would be okay as well if you didn’t use type ascription.
Edit
Notice as well here that you can just do what the compiler is hinting at…

1 Like

#4

another way you can do it uses nightly Rust using CoerceUnsized and Unsize

playground

4 Likes