I implemented a trait for another trait but cannot call methods from both traits

You need to implement the second trait for objects that implement the first trait:

impl<T> Sleep for T
where
    T: HasBed,
{
    fn sleep(&self) {
        self.sleep_in_bed()
    }
}

Previously, you were implementing Sleep for the trait’s type, better expressed as dyn HasBed. See What does “dyn” mean in a type? for more details.

However, this is going to break as soon as you add a second blanket implementation:

impl<T> Sleep for T
where
    T: HasTent,
{
    fn sleep(&self) {
        self.sleep_in_tent()
    }
}

With

error[E0119]: conflicting implementations of trait `Sleep`:
  --> src/main.rs:24:1
   |
10 | / impl<T> Sleep for T
11 | | where
12 | |     T: HasBed,
13 | | {
...  |
16 | |     }
17 | | }
   | |_- first implementation here
...
24 | / impl<T> Sleep for T
25 | | where
26 | |     T: HasTent,
27 | | {
...  |
30 | |     }
31 | | }
   | |_^ conflicting implementation

It’s possible for something to implement both HasBed and HasTent. If something were to appear that implemented both, then the code would now be ambiguous. The workaround for this would be specialization, but there’s no stable implementation of that yet.

How do you accomplish your goal? I think you have already suggested the current best solution – write a macro. You could also write your own derive macro. Macros really aren’t that bad, but they can be unwieldy to write.

Another thing, which may be entirely based on the names you chose for your example, would be to simply embed structs into other structs, optionally making them public. Since your implementation of Sleep basically only depends on the bed / tent, no functionality would be lost by doing this. Of course, some people might feel that breaks encapsulation. You could again create macros to implement a delegation of sorts.

trait Sleep {
    fn sleep(&self);
}

struct Bed;
impl Bed {
    fn jump(&self) {}
}
impl Sleep for Bed {
    fn sleep(&self) {}
}

struct Tent;
impl Tent {
    fn hide(&self) {}
}
impl Sleep for Tent {
    fn sleep(&self) {}
}

struct Jim {
    bed: Bed,
}
struct Jane {
    tent: Tent,
}

fn main() {
    let jim = Jim { bed: Bed };
    jim.bed.sleep();
}

Leave a Comment