Вызов методов объекта из дефолтной реализации трейта

Добрый день.
Не могу понять один момент, вот такой код не компилируется

struct MyStruct{
    x: i32
}

impl MyStruct{
    pub fn foo(&mut self){
        self.x = 5;
    }
}

trait Foo{
    fn foo_foo( &mut self )
    {
        self.foo();
    }
}

impl Foo for MyStruct{
}

fn main() {
    println!("Hello, world!");
}
error[E0599]: no method named `foo` found for type `&mut Self` in the current scope
  --> src/main.rs:14:14
   |
14 |         self.foo();
   |              ^^^

Из дефолтной реализации трейта нельзя вызвать метод объекта?
если переношу вызов из дефолтной реализации в конкретную то все Ок.

trait Foo{
    fn foo_foo( &mut self );
}

impl Foo for MyStruct{
    fn foo_foo( &mut self )
    {
        self.foo();
    }
}

Из дефолтной реализации трейта нельзя вызвать метод объекта?

Да, дефолтные реализации ничего про конкретные типы, для которых они реализуются, не знают.

Использовать можно только то, что предоставляет сам типаж или его требования (например, если Foo будет требовать Clone, то в умолчательном foo_foo можно будет делать .clone() объекта).

Подскажите, а как в Rust обычно реализуются такие вещи, мне нужно выполнить один и тот же код над объектами разного типа с вызовом у них одной и той же функции?
Только делаю конкретную реализацию как в примере выше или есть еще пути?

Только делаю конкретную реализацию как в примере выше или есть еще пути?

Да, для каждого типа нужна своя реализация - иначе типаж бы получился прибитым гвоздями только к одному типу.

Обычно как-то так код выглядит:

#[derive(Debug)]
struct A {
    x: i32,
}

#[derive(Debug)]
struct B {
    c: char,
}

trait Foo {
    fn foo(&mut self);
}

impl Foo for A {
    fn foo(&mut self) {
        self.x = 5;
    }
}

impl Foo for B {
    fn foo(&mut self) {
        self.c = 'F';
    }
}

fn do_same_thing_static_dispatch(f: &mut impl Foo) {
    println!("Doing something...");
    f.foo();
    println!("Doing something else...");
}

fn do_same_thing_dynamic_dispatch(f: &mut dyn Foo) {
    println!("Doing something...");
    f.foo();
    println!("Doing something else...");
}

fn main() {
    let mut a = A { x: 0 };
    let mut b = B { c: 'a' };
    do_same_thing_static_dispatch(&mut a);
    do_same_thing_static_dispatch(&mut b);
    do_same_thing_dynamic_dispatch(&mut a);
    do_same_thing_dynamic_dispatch(&mut b);
    dbg!(a, b);
}

Playground

Странно на мой взгляд, на момент компиляции все типы реализующие трейт известны, и проверить что там есть функция и с ней все ок, по идее можно.
Спасибо, а то думал, что не понял чего то, и делаю не правильно.

иначе типаж бы получился прибитым гвоздями только к одному типу

Вообще, да, это я странное написал там.

на момент компиляции все типы реализующие трейт известны, и проверить что там есть функция и с ней все ок, по идее можно

Да, в теории такое могло бы быть реализовано, конечно, что типажи втихоря выводили бы такие зависимости, но Rust в общем и целом склонен к явности, так что вот тут требует явно тут все выписать. Типа, что у нас не случайно метод (или еще что) с таким же названием попался у типа, а мы именно специально для этого типажа его писали.

Если у разных типов нужно вызывать одну и ту же функцию, по сути это говорит о том, что эта функция входит в их общий интерфейс. Стандартный способ сообщить об этом для Rust - сделать, чтобы эта функция входила в общий для них типаж. Тогда ей можно будет воспользоваться в реализации, если реализация этого типажа обязательна для интересующего нас типажа.

Если функция с идентичным смыслом, которую имеет смысл вызывать без знания точного типа, определена сама по себе, а не в типаже, на мой взгляд это не очень хороший признак.

Ну и да, компилятор не исходит из того, что в момент компиляции все типы известны. Они могут быть известны не все, и, более того, часть из них может быть определена вообще в других крейтах, если это публичный типаж.

Естественно трейт не знает об объекте ничего.
Он просто физически не в состоянии этого знать.
Поэтому метод foo должен быть частью интерфейса.
Примерно как-то так:

struct MyStruct{
    x: i32
}

trait Foo{
    fn foo( &mut self );

    fn foo_foo( &mut self )
    {
        self.foo();
    }
}

impl Foo for MyStruct{
    fn foo(&mut self){
        self.x = 5;
    }
}

fn main() {
    println!("Hello, world!");
}