]> git.proxmox.com Git - rustc.git/blame - src/doc/book/deref-coercions.md
New upstream version 1.16.0+dfsg1
[rustc.git] / src / doc / book / deref-coercions.md
CommitLineData
9346a6ac
AL
1% `Deref` coercions
2
bd371182
AL
3The standard library provides a special trait, [`Deref`][deref]. It’s normally
4used to overload `*`, the dereference operator:
5
6```rust
7use std::ops::Deref;
8
9struct DerefExample<T> {
10 value: T,
11}
12
13impl<T> Deref for DerefExample<T> {
14 type Target = T;
15
16 fn deref(&self) -> &T {
17 &self.value
18 }
19}
20
21fn main() {
22 let x = DerefExample { value: 'a' };
23 assert_eq!('a', *x);
24}
25```
26
27[deref]: ../std/ops/trait.Deref.html
28
29This is useful for writing custom pointer types. However, there’s a language
30feature related to `Deref`: ‘deref coercions’. Here’s the rule: If you have a
31type `U`, and it implements `Deref<Target=T>`, values of `&U` will
32automatically coerce to a `&T`. Here’s an example:
33
34```rust
35fn foo(s: &str) {
476ff2be 36 // Borrow a string for a second.
bd371182
AL
37}
38
476ff2be 39// String implements Deref<Target=str>.
bd371182
AL
40let owned = "Hello".to_string();
41
476ff2be 42// Therefore, this works:
bd371182
AL
43foo(&owned);
44```
45
46Using an ampersand in front of a value takes a reference to it. So `owned` is a
47`String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for
48String`, `&String` will deref to `&str`, which `foo()` takes.
49
50That’s it. This rule is one of the only places in which Rust does an automatic
51conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>`
52type implements `Deref<Target=T>`, so this works:
53
54```rust
55use std::rc::Rc;
56
57fn foo(s: &str) {
476ff2be 58 // Borrow a string for a second.
bd371182
AL
59}
60
476ff2be 61// String implements Deref<Target=str>.
bd371182
AL
62let owned = "Hello".to_string();
63let counted = Rc::new(owned);
64
476ff2be 65// Therefore, this works:
bd371182
AL
66foo(&counted);
67```
68
69All we’ve done is wrap our `String` in an `Rc<T>`. But we can now pass the
70`Rc<String>` around anywhere we’d have a `String`. The signature of `foo`
71didn’t change, but works just as well with either type. This example has two
c30ab7b3 72conversions: `&Rc<String>` to `&String` and then `&String` to `&str`. Rust will do
bd371182
AL
73this as many times as possible until the types match.
74
75Another very common implementation provided by the standard library is:
76
77```rust
78fn foo(s: &[i32]) {
476ff2be 79 // Borrow a slice for a second.
bd371182
AL
80}
81
476ff2be 82// Vec<T> implements Deref<Target=[T]>.
bd371182
AL
83let owned = vec![1, 2, 3];
84
85foo(&owned);
86```
87
88Vectors can `Deref` to a slice.
89
90## Deref and method calls
91
e9174d1e
SL
92`Deref` will also kick in when calling a method. Consider the following
93example.
bd371182
AL
94
95```rust
96struct Foo;
97
98impl Foo {
99 fn foo(&self) { println!("Foo"); }
100}
101
e9174d1e 102let f = &&Foo;
bd371182
AL
103
104f.foo();
105```
106
e9174d1e
SL
107Even though `f` is a `&&Foo` and `foo` takes `&self`, this works. That’s
108because these things are the same:
bd371182
AL
109
110```rust,ignore
111f.foo();
112(&f).foo();
113(&&f).foo();
114(&&&&&&&&f).foo();
115```
116
117A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo`
118called, because the compiler will insert as many * operations as necessary to
119get it right. And since it’s inserting `*`s, that uses `Deref`.