🎓 A1Learner
🔍

Rust Same-Name Methods

Same-name methods are methods that share one name on one type. Each method comes from a different trait, or from the type itself.

Three methods, one name

Two traits may both define a method with the same name, and one type may implement both. A type may also have its own method with that same name:

impl Pilot for Human { fn fly(&self) { println!("This is your captain speaking."); } }
impl Wizard for Human { fn fly(&self) { println!("Up!"); } }
impl Human { fn fly(&self) { println!("*waving arms furiously*"); } }

The short call picks the own method

Call value.fly() and Rust picks the method written directly on the type:

let person = Human;
person.fly();

Name the trait to pick its version

Call Pilot::fly(&value) to pick a trait version: name the trait, and pass the value as the first input:

Pilot::fly(&person);
Wizard::fly(&person);

A trait can require another trait first

trait OutlinePrint: Display is a supertrait. A type must implement Display before it may implement OutlinePrint, and OutlinePrint may use the methods of Display:

trait OutlinePrint: Display {}

Associated functions need the full name

Associated functions have no self, so a trait name alone is not enough: Animal::baby_name() fails with error E0790. Use fully qualified syntax — <Dog as Animal>::baby_name() says the type and the trait together:

let name = <Dog as Animal>::baby_name();
println!("{}", name);

Same name, different return types

Two traits may share a method name even with different return types, because each impl lives in its own block. Fully qualified syntax settles which one a call means:

trait AgeWidget { fn get(&self) -> u8; }
trait NameWidget { fn get(&self) -> String; }
struct Form;
impl AgeWidget for Form { fn get(&self) -> u8 { 42 } }
impl NameWidget for Form { fn get(&self) -> String { String::from("Ada") } }
let form = Form;
println!("{} {}", <Form as AgeWidget>::get(&form), <Form as NameWidget>::get(&form));

Example

trait Pilot { fn fly(&self); }
trait Wizard { fn fly(&self); }
struct Human;
impl Pilot for Human { fn fly(&self) { println!("This is your captain speaking."); } }
impl Wizard for Human { fn fly(&self) { println!("Up!"); } }
impl Human { fn fly(&self) { println!("*waving arms furiously*"); } }
fn main() {
    let person = Human;
    Pilot::fly(&person);
    Wizard::fly(&person);
    person.fly();
}

Key points

  • If a type has no method of its own and two of its traits share a name, value.get() fails with a "multiple get found" error: neither trait wins by default
  • Same-name methods share one name on one type, each from a different source.

In this example, Human has three fly methods: one from Pilot, one from Wizard, and one of its own. Pilot::fly(&person) names the trait, so the captain line prints. Wizard::fly(&person) prints Up!. Plain person.fly() picks the method written directly on Human, so the arm-waving line prints last.

Note

Fully qualified syntax <Type as Trait>::name(...) works for any call.

You only need it when the short form is ambiguous.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

How do you call the Wizard version of fly on a Human value?