Trait inheritance and implementation of methods inside trait?


#1

I can not understand how implementation of method inside trait
and trait inheritance cooperate, can anybody explain?
Consider such code:

#[derive(Debug, Clone)]
struct X;

trait Parent {
    fn f_ref(&self, x: &X);
}

trait Foo: Parent {
    fn f_ref(&self, x: &X) {
        self.f_val(x.clone());
    }
    fn f_val(&self, x: X);
}

From what I read, trait Foo: Parent just mean that self inside Foo should implements
trait Parent. But what if Foo like in my example implement all methods of Parent?

Obviously if you try just write:

impl Foo for i32 {
    fn f_val(&self, x: X) {}
} 

compile requires impl Parent for i32 and doesn’t compile code.
So implementation of f_ref inside trait Foo is useless, but why then
compile allow it?


#2

Foo does not implement Parent::f_ref it adds an entirely different function Foo::f_ref that only has the same base name.


#3

Foo does not implement Parent::f_ref it adds an entirely different function Foo::f_ref that only has the same base name.

But rust not allow function name overloading, why it allowed here?


#4

This isn’t considered function overloading because the functions come from different trait impls. If you consider Universal Function Call Syntax, then you have Parent::f_ref and Foo::f_ref - different functions.

If you impl Parent and Foo for i32, the following won’t compile:

let x = 5i32;
x.f_ref();

You’ll need to disambiguate via UFCS, eg Parent::f_ref(&x).

Note that I took the X out of the fn signature, but it would be the same thing.


#5

trait Foo: Parent does not really mean inheritance. It means “you can’t implement Foo without also implementing Parent”.

<T as Foo>::f_ref(self, x) and <T as Parent>::f_ref(self, x) remain to be two completely separate methods.


#6

instead of making Parent a requirement of Foo you can actually impl Parent for Foo like this

playground

impl Parent for Foo {
    fn f_ref(&self, x: &X) {
        self.f_val(x.clone());
    }
}