In this lesson, you will learn how to resolve compiler ambiguity when a single type implements multiple traits that define methods with identical names.
The Problem: Naming Collisions
Sometimes, you might define two different traits that happen to share a method name. If your struct implements both, calling that method directly on an instance leads to a compilation error: "multiple applicable items in scope." Rust doesn't know which one you intend to use.
Consider these traits:
trait Pilot {
fn fly(&self);
}
trait Wizard {
fn fly(&self);
}
struct Human;
impl Pilot for Human { fn fly(&self) { println!("Taking off!"); } }
impl Wizard for Human { fn fly(&self) { println!("Up and away!"); } }
If you try let h = Human; h.fly();, the compiler will panic (at compile time) because it can't distinguish between the two fly methods.
The Solution: Fully Qualified Syntax
To resolve this, we use Fully Qualified Syntax. Instead of calling the method directly on the object, we specify exactly which trait we are invoking. The syntax follows this pattern: <Type as Trait>::method(receiver).
fn main() {
let h = Human;
// Direct calls are ambiguous:
// h.fly(); // Error!
// Resolved calls:
<Human as Pilot>::fly(&h); // Prints: Taking off!
<Human as Wizard>::fly(&h); // Prints: Up and away!
}
Why This Matters
This pattern is especially vital when working with complex generic code. If you have a generic function where a type T implements two traits that both provide a method like new() or log(), you cannot rely on simple dot notation. By using the Type as Trait syntax, you explicitly tell the compiler which implementation to invoke, maintaining the efficiency of static dispatch while clearing up the ambiguity.
This syntax treats the method as a standard function where you pass the instance (often a reference) as the first argument, effectively bypassing the ambiguity of the method dispatch system.
Key Takeaway: When multiple traits share a method name, use the fully qualified syntax <Type as Trait>::method(instance) to explicitly tell Rust which implementation you intended to call.