Skip to content

Inherent/trait method priority rules exist, but are unclear and seem to be undocumented #26007

Closed
@niconii

Description

@niconii

Consider this code:

struct Foo;

impl Foo {
    fn foo(&self) {
        println!("Foo");
    }
}

trait Bar {
    fn foo(&self);
}

impl Bar for Foo {
    fn foo(&self) { 
        println!("Bar"); 
    }
}

fn main() {
    let mut f = Foo;
    f.foo();
}

Unlike a method name conflict between two traits, Rust will compile this code, which will produce:

Foo

One might conclude that the inherent method (i.e. belonging to the type itself) Foo::foo() has priority over the trait method Bar::foo(). Yet, if we change the signature of Foo::foo() to fn foo(&mut self) in this code, suddenly the program outputs:

Bar

So it would seem the type of arguments also plays some role in which method is chosen. To try and understand the rules behind it, I created the following table which shows the output for each combination of self's type in Foo::foo() and Bar::foo():

Bar↓ Foo→ &Self &mut Self Self
&Self Foo Bar Foo
&mut Self Foo Foo Foo
Self Bar Bar Foo

Looking at this, I think I can deduce that:

  1. Inherent methods indeed have priority over trait methods when types are equal.
  2. The priority of types is &mut Self < &Self < Self.

That said, these rules are not terribly intuitive, and I'm unsure how they stack up against more complex method signatures. It would be good to have documentation about this.

Another concern of mine, however, is the inconsistency between this and a situation involving multiple trait methods conflicting. In that situation, rustc gives an error and asks the programmer to specify which trait's method should be used via UFCS. I'd prefer something like that over the current situation, though I'm not sure it's possible to do backwards-compatibly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsA-type-systemArea: Type system

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions