Skip to content

Commit a04a07a

Browse files
committed
TRPL: UFCS
AKA, two four-letter acronyms 😉
1 parent 3860240 commit a04a07a

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

src/doc/trpl/ufcs.md

+82-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,84 @@
11
% Universal Function Call Syntax
22

3-
Coming soon
3+
Sometimes, functions can have the same names. Consider this code:
4+
5+
```rust
6+
trait Foo {
7+
fn f(&self);
8+
}
9+
10+
trait Bar {
11+
fn f(&self);
12+
}
13+
14+
struct Baz;
15+
16+
impl Foo for Baz {
17+
fn f(&self) { println!("Baz’s impl of Foo"); }
18+
}
19+
20+
impl Bar for Baz {
21+
fn f(&self) { println!("Baz’s impl of Bar"); }
22+
}
23+
24+
let b = Baz;
25+
```
26+
27+
If we were to try to call `b.f()`, we’d get an error:
28+
29+
```text
30+
error: multiple applicable methods in scope [E0034]
31+
b.f();
32+
^~~
33+
note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
34+
`main::Baz`
35+
fn f(&self) { println!("Baz’s impl of Foo"); }
36+
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37+
note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
38+
`main::Baz`
39+
fn f(&self) { println!("Baz’s impl of Bar"); }
40+
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41+
42+
```
43+
44+
We need a way to disambiguate which method we need. This feature is called
45+
‘universal function call syntax’, and it looks like this:
46+
47+
```rust
48+
# trait Foo {
49+
# fn f(&self);
50+
# }
51+
# trait Bar {
52+
# fn f(&self);
53+
# }
54+
# struct Baz;
55+
# impl Foo for Baz {
56+
# fn f(&self) { println!("Baz’s impl of Foo"); }
57+
# }
58+
# impl Bar for Baz {
59+
# fn f(&self) { println!("Baz’s impl of Bar"); }
60+
# }
61+
# let b = Baz;
62+
<Baz as Foo>::f(&b);
63+
<Baz as Bar>::f(&b);
64+
```
65+
66+
Let’s break it down.
67+
68+
```rust,ignore
69+
<Baz as Foo>::
70+
```
71+
72+
The `<>::` syntax is a means of providing a type hint. The type goes inside the `<>`s.
73+
In this case, the type is `Baz as Foo`, indicating that we want `Foo`, not `Bar`, to
74+
be called here.
75+
76+
```rust,ignore
77+
f(&b)
78+
```
79+
80+
When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
81+
will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
82+
not, and so we need to pass an explicit `&b`.
83+
84+
[methodsyntax]: method-syntax.html

0 commit comments

Comments
 (0)