]> git.lizzy.rs Git - rust.git/commitdiff
TRPL: UFCS
authorSteve Klabnik <steve@steveklabnik.com>
Tue, 21 Apr 2015 16:07:00 +0000 (12:07 -0400)
committerSteve Klabnik <steve@steveklabnik.com>
Wed, 22 Apr 2015 22:30:27 +0000 (18:30 -0400)
AKA, two four-letter acronyms :wink:

src/doc/trpl/ufcs.md

index 6b9a417c43944ae883642c8642a3a5081d2617bf..2d5c742ddb8482312a2ee0661f46808b694c8c50 100644 (file)
@@ -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.