rust/src/doc/trpl/ufcs.md
Toni Cárdenas df1768d8eb TRPL: Tiny incoherence in UFCS example.
`Type` should be `Trait` to match the next example line.

r? @steveklabnik
2015-04-28 11:10:01 +02:00

128 lines
2.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

% Universal Function Call Syntax
Sometimes, functions can have the same names. Consider this code:
```rust
trait Foo {
fn f(&self);
}
trait Bar {
fn f(&self);
}
struct Baz;
impl Foo for Baz {
fn f(&self) { println!("Bazs impl of Foo"); }
}
impl Bar for Baz {
fn f(&self) { println!("Bazs impl of Bar"); }
}
let b = Baz;
```
If we were to try to call `b.f()`, wed get an error:
```text
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!("Bazs 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!("Bazs 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:
```rust
# trait Foo {
# fn f(&self);
# }
# trait Bar {
# fn f(&self);
# }
# struct Baz;
# impl Foo for Baz {
# fn f(&self) { println!("Bazs impl of Foo"); }
# }
# impl Bar for Baz {
# fn f(&self) { println!("Bazs impl of Bar"); }
# }
# let b = Baz;
Foo::f(&b);
Bar::f(&b);
```
Lets break it down.
```rust,ignore
Foo::
Bar::
```
These halves of the invocation are the types of the two traits: `Foo` and
`Bar`. This is what ends up actually doing the disambiguation between the two:
Rust calls the one from the trait name you use.
```rust,ignore
f(&b)
```
When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
not, and so we need to pass an explicit `&b`.
[methodsyntax]: method-syntax.html
# Angle-bracket Form
The form of UFCS we just talked about:
```rust,ignore
Trait::method(args);
```
Is a short-hand. Theres an expanded form of this thats needed in some
situations:
```rust,ignore
<Type as Trait>::method(args);
```
The `<>::` syntax is a means of providing a type hint. The type goes inside
the `<>`s. In this case, the type is `Type as Trait`, indicating that we want
`Trait`s version of `method` to be called here. The `as Trait` part is
optional if its not ambiguous. Same with the angle brackets, hence the
shorter form.
Heres an example of using the longer form.
```rust
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` traits `clone()` method, rather than `Foo`s.