]> git.proxmox.com Git - rustc.git/blob - src/doc/book/src/borrow-and-asref.md
New upstream version 1.17.0+dfsg1
[rustc.git] / src / doc / book / src / borrow-and-asref.md
1 # Borrow and AsRef
2
3 The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but
4 different. Here’s a quick refresher on what these two traits mean.
5
6 [borrow]: ../std/borrow/trait.Borrow.html
7 [asref]: ../std/convert/trait.AsRef.html
8
9 # Borrow
10
11 The `Borrow` trait is used when you’re writing a data structure, and you want to
12 use either an owned or borrowed type as synonymous for some purpose.
13
14 For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`:
15
16 ```rust,ignore
17 fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
18 where K: Borrow<Q>,
19 Q: Hash + Eq
20 ```
21
22 [hashmap]: ../std/collections/struct.HashMap.html
23 [get]: ../std/collections/struct.HashMap.html#method.get
24
25 This signature is pretty complicated. The `K` parameter is what we’re interested
26 in here. It refers to a parameter of the `HashMap` itself:
27
28 ```rust,ignore
29 struct HashMap<K, V, S = RandomState> {
30 ```
31
32 The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at
33 the signature of `get()` again, we can use `get()` when the key implements
34 `Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys,
35 but use `&str`s when we’re searching:
36
37 ```rust
38 use std::collections::HashMap;
39
40 let mut map = HashMap::new();
41 map.insert("Foo".to_string(), 42);
42
43 assert_eq!(map.get("Foo"), Some(&42));
44 ```
45
46 This is because the standard library has `impl Borrow<str> for String`.
47
48 For most types, when you want to take an owned or borrowed type, a `&T` is
49 enough. But one area where `Borrow` is effective is when there’s more than one
50 kind of borrowed value. This is especially true of references and slices: you
51 can have both an `&T` or a `&mut T`. If we wanted to accept both of these types,
52 `Borrow` is up for it:
53
54 ```rust
55 use std::borrow::Borrow;
56 use std::fmt::Display;
57
58 fn foo<T: Borrow<i32> + Display>(a: T) {
59 println!("a is borrowed: {}", a);
60 }
61
62 let mut i = 5;
63
64 foo(&i);
65 foo(&mut i);
66 ```
67
68 This will print out `a is borrowed: 5` twice.
69
70 # AsRef
71
72 The `AsRef` trait is a conversion trait. It’s used for converting some value to
73 a reference in generic code. Like this:
74
75 ```rust
76 let s = "Hello".to_string();
77
78 fn foo<T: AsRef<str>>(s: T) {
79 let slice = s.as_ref();
80 }
81 ```
82
83 # Which should I use?
84
85 We can see how they’re kind of the same: they both deal with owned and borrowed
86 versions of some type. However, they’re a bit different.
87
88 Choose `Borrow` when you want to abstract over different kinds of borrowing, or
89 when you’re building a data structure that treats owned and borrowed values in
90 equivalent ways, such as hashing and comparison.
91
92 Choose `AsRef` when you want to convert something to a reference directly, and
93 you’re writing generic code.