Search code examples
rusttraits

Error when trying to implement a function declared in a supertrait


I'm trying to implement a trait that has a supertrait, like so:

trait A {
    fn do_a(&self);
}

trait B: A {
    fn do_b(&self);
}

struct S {}

impl B for S {
    fn do_a(&self) {}
    fn do_b(&self) {}
}

When I run cargo build I get these compiler errors:

error[E0407]: method `do_a` is not a member of trait `B`
  --> src/example.rs:12:5
   |
12 |     fn do_a(&self) {}
   |     ^^^^^^^^^^^^^^^^^ not a member of trait `B`

error[E0277]: the trait bound `example::S: example::A` is not satisfied
  --> src/example.rs:11:6
   |
5  | trait B: A {
   |          - required by this bound in `example::B`
...
11 | impl B for S {
   |      ^ the trait `example::A` is not implemented for `example::S`

I keep re-reading about supertraits, but I'm having trouble understanding this error.

  • The first error seems to contradict what trait B: A is telling the program to do.
  • The second error seems to contradict that the implementation of do_a(&self) {} satisfies A.

What am I missing here? Is my mental model wrong, or is my code missing some necessary boilerplate, or both?


Solution

  • I believe that the syntax is more about bounding the type (e.g. a type T that implements B must necessarily implement A) than inheritance in the object-oriented sense. If you write out the impls separately it compiles fine:

    trait A {
        fn do_a(&self);
    }
    
    trait B: A {
        fn do_b(&self);
    }
    
    struct S {}
    
    impl A for S {
        fn do_a(&self) {}
    }
    
    impl B for S {
        fn do_b(&self) {}
    }
    

    Playground

    N.B. that if you remove the impl for A the code no longer compiles, the constraint that an impl of B must also impl A is no longer satisfied.