diff options
| author | bors <bors@rust-lang.org> | 2015-04-23 12:04:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-04-23 12:04:01 +0000 |
| commit | 1114fcd945f6e979660053aeed561bcfb5da669e (patch) | |
| tree | a94099b59d822f5bafd525f5de76c1e588d5cb82 | |
| parent | 879c96225b3955b502fa795ee4d07d327ba08f84 (diff) | |
| parent | b97b0e3929030693f5cf0498e5639580a8089fdf (diff) | |
| download | rust-1114fcd945f6e979660053aeed561bcfb5da669e.tar.gz rust-1114fcd945f6e979660053aeed561bcfb5da669e.zip | |
Auto merge of #24664 - steveklabnik:doc_ufcs, r=alexcrichton
AKA, two four-letter acronyms :wink: This feels a bit light, if there's other things I should add, let me know.
| -rw-r--r-- | src/doc/trpl/ufcs.md | 126 |
1 files changed, 125 insertions, 1 deletions
diff --git a/src/doc/trpl/ufcs.md b/src/doc/trpl/ufcs.md index 6b9a417c439..2d5c742ddb8 100644 --- a/src/doc/trpl/ufcs.md +++ b/src/doc/trpl/ufcs.md @@ -1,3 +1,127 @@ % Universal Function Call Syntax -Coming soon +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!("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()`, we’d 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!("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: + +```rust +# 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); +``` + +Let’s 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 +Type::method(args); +``` + +Is a short-hand. There’s an expanded form of this that’s 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 it’s not ambiguous. Same with the angle brackets, hence the +shorter form. + +Here’s 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` trait’s `clone()` method, rather than `Foo`’s. |
