Skip to content

Commit 930baef

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

File tree

1 file changed

+126
-1
lines changed

1 file changed

+126
-1
lines changed

src/doc/trpl/ufcs.md

+126-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,128 @@
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+
Foo::f(&b);
63+
Bar::f(&b);
64+
```
65+
66+
Let’s break it down.
67+
68+
```rust,ignore
69+
Foo::
70+
Bar::
71+
```
72+
73+
These halves of the invocation are the types of the two traits: `Foo` and
74+
`Bar`. This is what ends up actually doing the disambiguation between the two:
75+
Rust calls the one from the trait name you use.
76+
77+
```rust,ignore
78+
f(&b)
79+
```
80+
81+
When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
82+
will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
83+
not, and so we need to pass an explicit `&b`.
84+
85+
[methodsyntax]: method-syntax.html
86+
87+
# Angle-bracket Form
88+
89+
The form of UFCS we just talked about:
90+
91+
```rust,ignore
92+
Type::method(args);
93+
```
94+
95+
Is a short-hand. There’s an expanded form of this that’s needed in some
96+
situations:
97+
98+
```rust,ignore
99+
<Type as Trait>::method(args);
100+
```
101+
102+
The `<>::` syntax is a means of providing a type hint. The type goes inside the
103+
`<>`s. In this case, the type is `Type as Trait`, indicating that we want
104+
`Trait`’s version of `method` to be called here. The `as Trait` part is
105+
optional if it’s not ambiguous, and if you’ve left it off, the angle brackets
106+
are too. Hence the shorter form.
107+
108+
You need this version if you’re doing something like this:
109+
110+
```rust
111+
trait Foo {
112+
fn clone(&self);
113+
}
114+
115+
#[derive(Clone)]
116+
struct Bar;
117+
118+
impl Foo for Bar {
119+
fn clone(&self) {
120+
println!("Making a clone of Bar");
121+
<Bar as Clone>::clone(self);
122+
}
123+
}
124+
```
125+
126+
The only way to choose `Clone::clone()` over `Foo::clone()` is to use this
127+
syntax.
128+

0 commit comments

Comments
 (0)