Skip to content

Commit 1114fcd

Browse files
committed
Auto merge of #24664 - steveklabnik:doc_ufcs, r=alexcrichton
AKA, two four-letter acronyms 😉 This feels a bit light, if there's other things I should add, let me know.
2 parents 879c962 + b97b0e3 commit 1114fcd

File tree

1 file changed

+125
-1
lines changed

1 file changed

+125
-1
lines changed

src/doc/trpl/ufcs.md

+125-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,127 @@
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
103+
the `<>`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. Same with the angle brackets, hence the
106+
shorter form.
107+
108+
Here’s an example of using the longer form.
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+
122+
<Bar as Clone>::clone(self);
123+
}
124+
}
125+
```
126+
127+
This will call the `Clone` trait’s `clone()` method, rather than `Foo`’s.

0 commit comments

Comments
 (0)