Sometimes, functions can have the same names. Consider this code:
fn main() { trait Foo { fn f(&self); } trait Bar { fn f(&self); } struct Baz; impl Foo for Baz { fn f(&self) { println!("Baz’s impl of Foo"); } } impl Bar for Baz { fn f(&self) { println!("Baz’s impl of Bar"); } } let b = Baz; }trait Foo { fn f(&self); } trait Bar { fn f(&self); } struct Baz; impl Foo for Baz { fn f(&self) { println!("Baz’s impl of Foo"); } } impl Bar for Baz { fn f(&self) { println!("Baz’s impl of Bar"); } } let b = Baz;
If we were to try to call b.f()
`b.f()`, we’d get an error:
error: multiple applicable methods in scope [E0034]
b.f();
^~~
note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
`main::Baz`
fn f(&self) { println!("Baz’s impl of Foo"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
`main::Baz`
fn f(&self) { println!("Baz’s impl of Bar"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We need a way to disambiguate which method we need. This feature is called ‘universal function call syntax’, and it looks like this:
fn main() { trait Foo { fn f(&self); } trait Bar { fn f(&self); } struct Baz; impl Foo for Baz { fn f(&self) { println!("Baz’s impl of Foo"); } } impl Bar for Baz { fn f(&self) { println!("Baz’s impl of Bar"); } } let b = Baz; Foo::f(&b); Bar::f(&b); }Foo::f(&b); Bar::f(&b);
Let’s break it down.
fn main() { Foo:: Bar:: }Foo:: Bar::
These halves of the invocation are the types of the two traits: Foo
`Fooand
` and
Bar
`Bar`. This is what ends up actually doing the disambiguation between the two:
Rust calls the one from the trait name you use.
f(&b)
When we call a method like b.f()
`b.f()using [method syntax][methodsyntax], Rust will automatically borrow
` using method syntax, Rust
will automatically borrow b
`bif
` if f()
`f()takes
` takes &self
`&self. In this case, Rust will not, and so we need to pass an explicit
`. In this case, Rust will
not, and so we need to pass an explicit &b
`&b`.
The form of UFCS we just talked about:
fn main() { Trait::method(args); }Trait::method(args);
Is a short-hand. There’s an expanded form of this that’s needed in some situations:
fn main() { <Type as Trait>::method(args); }<Type as Trait>::method(args);
The <>::
`<>::syntax is a means of providing a type hint. The type goes inside the
` syntax is a means of providing a type hint. The type goes inside
the <>
`<>s. In this case, the type is
`s. In this case, the type is Type as Trait
`Type as Trait, indicating that we want
`, indicating that we want
Trait
`Trait’s version of
`’s version of method
`methodto be called here. The
` to be called here. The as Trait
`as Trait` part is
optional if it’s not ambiguous. Same with the angle brackets, hence the
shorter form.
Here’s an example of using the longer form.
fn main() { trait Foo { fn clone(&self); } #[derive(Clone)] struct Bar; impl Foo for Bar { fn clone(&self) { println!("Making a clone of Bar"); <Bar as Clone>::clone(self); } } }trait Foo { fn clone(&self); } #[derive(Clone)] struct Bar; impl Foo for Bar { fn clone(&self) { println!("Making a clone of Bar"); <Bar as Clone>::clone(self); } }
This will call the Clone
`Clonetrait’s
` trait’s clone()
`clone()method, rather than
` method, rather than Foo
`Foo`’s.