Trouble with Trait disambiguation

I'm trying to understand how structs handle overriding method implementations. On the example below, the Foo trait has a method, baz, which has a default implementation. The struct below, FooBar, overrides that implementation. In the main method, I try to call the method from Foo on an instance of FooBar by using the full name of the trait, i.e. Foo::bar(&foobar_instance), however, it does not call the trait's default implementation, but instead calls the method as implemented by FooBar.

trait Foo {
    fn bar(&self) -> u64;
    fn baz(&self) {
        println!("Bar is {}", self.bar());
    }
}

/// Struct with bar value field
struct FooBar {
    val: u64,
}

impl FooBar {
    fn new(val: u64) -> Self {
        FooBar { val }
    }
}

impl Foo for FooBar {
    fn bar(&self) -> u64 {
        self.val
    }
    
    fn baz(&self) {
        println!("FooBar says bar is: {}", self.bar());
    }
}

fn main() {
    let a = FooBar::new(5);
    // Expected: Bar is 5
    // Actual: FooBar says bar is: 5
    Foo::baz(&a);
    // Expected: FooBar says bar is: 5
    // Actual: FooBar says bar is: 5
    a.baz();
}

(Playground)

Is there a way to call the default implementation from the Foo trait for this object, or is this not possible in Rust?

There is not. You need to factor it out into a function and expose that.

pub trait Foo {
    fn bar(&self) -> u64;
    fn baz(&self) { default_baz(self) }
}

pub fn default_baz<T: Foo + ?Sized>(value: &T) {
    println!("Bar is {}", value.bar());
}
2 Likes