0

The latest stable version of Rust (1.27) allows implementing a trait for trait objects (dyn Trait), so I tried the following:

trait T1 {
    fn f1(&self);
}
trait T2 {
    fn f2(&self);
}
impl T2 for dyn T1 {
    fn f2(&self) {
        self.f1()
    }
}
struct S();
impl T1 for S {
    fn f1(&self) {}
}

fn main() {
    let t1 = S();
    let t12: &T1 = &t1;
    t12.f2();
    let t2: &T2 = &t12;
    t2.f2();
}

The above code results in an error:

error[E0277]: the trait bound `&T1: T2` is not satisfied
  --> src/main.rs:21:19
   |
21 |     let t2: &T2 = &t12;
   |                   -^^^
   |                   |
   |                   the trait `T2` is not implemented for `&T1`
   |                   help: consider removing 1 leading `&`-references
   |
   = help: the following implementations were found:
             <T1 + 'static as T2>
   = note: required for the cast to the object type `T2`

This is confusing as &T1 is an instance of dyn T1 and so has a T2 implementation. We can even witness this by the fact that we can call f2 on t12 directly, as removing the last two lines in main makes it compile.

Is it possible to create a trait object from a trait object that marked as a different trait?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Earth Engine
  • 10,048
  • 5
  • 48
  • 78
  • 1
    *The latest stable version of Rust (1.27) allows* — This has been allowed **since Rust 1.0**. The only thing that's new is the literal `dyn` keyword. Your code behaves the same without it (`impl T2 for T1 { /* ... */ }`). – Shepmaster Jul 07 '18 at 13:59

1 Answers1

3

You are implementing T2 for a trait object itself (dyn T1), but trying to use it for a reference to a trait object (&dyn T1).

Try impl<'a> T2 for &'a dyn T1 { ... } instead. This means "For any lifetime 'a, implement T2 for a reference that is valid for 'a and refers to a T1-trait object".
I don't know any good use of impl ... for dyn ... itself.

Adjusted code from the question in the playground

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Vi.
  • 37,014
  • 18
  • 93
  • 148
  • [Why would I implement methods on a trait instead of as part of the trait?](https://stackoverflow.com/q/34438755/155423); [When should I not implement a trait for references to implementors of that trait?](https://stackoverflow.com/q/28799372/155423). – Shepmaster Jul 07 '18 at 14:06
  • There is of cause a use: as an "extended" trait of `T1` so we can call methods from `T2` rather than `T1`, like the way I wrote `t12.f2()`. But if this is the only reason we should use `impl T2 for T where T: T1` instead... – Earth Engine Jul 08 '18 at 12:53