|
14 | 14 |
|
15 | 15 | /// A trait for borrowing data.
|
16 | 16 | ///
|
17 |
| -/// In general, there may be several ways to "borrow" a piece of data. The |
18 |
| -/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` |
19 |
| -/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of |
20 |
| -/// borrows: the borrowed slices `&[T]` and `&mut [T]`. |
| 17 | +/// In Rust, it is common to provide different representations of a type for |
| 18 | +/// different use cases. For instance, storage location and management for a |
| 19 | +/// value can be specifically chosen as appropriate for a particular use via |
| 20 | +/// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic |
| 21 | +/// wrappers that can be used with any type, some types provide optional |
| 22 | +/// facets providing potentially costly functionality. An example for such a |
| 23 | +/// type is [`String`] which adds the ability to extend a string to the basic |
| 24 | +/// [`str`]. This requires keeping additional information unnecessary for a |
| 25 | +/// simple, immutable string. |
21 | 26 | ///
|
22 |
| -/// When writing generic code, it is often desirable to abstract over all ways |
23 |
| -/// of borrowing data from a given type. That is the role of the `Borrow` |
24 |
| -/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given |
25 |
| -/// type can be borrowed as multiple different types. In particular, `Vec<T>: |
26 |
| -/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`. |
| 27 | +/// These types provide access to the underlying data through references |
| 28 | +/// to the type of that data. They are said to be ‘borrowed as’ that type. |
| 29 | +/// For instance, a [`Box<T>`] can be borrowed as `T` while a [`String`] |
| 30 | +/// can be borrowed as `str`. |
27 | 31 | ///
|
28 |
| -/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement |
29 |
| -/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result. |
| 32 | +/// Types express that they can be borrowed as some type `T` by implementing |
| 33 | +/// `Borrow<T>`, providing a reference to a `T` in the trait’s |
| 34 | +/// [`borrow`] method. A type is free to borrow as several different types. |
| 35 | +/// If it wishes to mutably borrow as the type – allowing the underlying data |
| 36 | +/// to be modified, it can additionally implement [`BorrowMut<T>`]. |
30 | 37 | ///
|
31 |
| -/// `Borrow` is very similar to, but different than, `AsRef`. See |
32 |
| -/// [the book][book] for more. |
| 38 | +/// Further, when providing implementations for additional traits, it needs |
| 39 | +/// to be considered whether they should behave identical to those of the |
| 40 | +/// underlying type as a consequence of acting as a representation of that |
| 41 | +/// underlying type. Generic code typically uses `Borrow<T>` when it relies |
| 42 | +/// on the identical behavior of these additional trait implementations. |
| 43 | +/// These traits will likely appear as additional trait bounds. |
33 | 44 | ///
|
34 |
| -/// [book]: ../../book/first-edition/borrow-and-asref.html |
| 45 | +/// If generic code merely needs to work for all types that can |
| 46 | +/// provide a reference to related type `T`, it is often better to use |
| 47 | +/// [`AsRef<T>`] as more types can safely implement it. |
| 48 | +/// |
| 49 | +/// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html |
| 50 | +/// [`BorrowMut<T>`]: trait.BorrowMut.html |
| 51 | +/// [`Box<T>`]: ../../std/boxed/struct.Box.html |
| 52 | +/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html |
| 53 | +/// [`Rc<T>`]: ../../std/rc/struct.Rc.html |
| 54 | +/// [`str`]: ../../std/primitive.str.html |
| 55 | +/// [`String`]: ../../std/string/struct.String.html |
| 56 | +/// [`borrow`]: #tymethod.borrow |
| 57 | +/// |
| 58 | +/// # Examples |
| 59 | +/// |
| 60 | +/// As a data collection, [`HashMap<K, V>`] owns both keys and values. If |
| 61 | +/// the key’s actual data is wrapped in a managing type of some kind, it |
| 62 | +/// should, however, still be possible to search for a value using a |
| 63 | +/// reference to the key’s data. For instance, if the key is a string, then |
| 64 | +/// it is likely stored with the hash map as a [`String`], while it should |
| 65 | +/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to |
| 66 | +/// operate on a `String` while `get` needs to be able to use a `&str`. |
| 67 | +/// |
| 68 | +/// Slightly simplified, the relevant parts of `HashMap<K, V>` look like |
| 69 | +/// this: |
| 70 | +/// |
| 71 | +/// ``` |
| 72 | +/// use std::borrow::Borrow; |
| 73 | +/// use std::hash::Hash; |
| 74 | +/// |
| 75 | +/// pub struct HashMap<K, V> { |
| 76 | +/// # marker: ::std::marker::PhantomData<(K, V)>, |
| 77 | +/// // fields omitted |
| 78 | +/// } |
| 79 | +/// |
| 80 | +/// impl<K, V> HashMap<K, V> { |
| 81 | +/// pub fn insert(&self, key: K, value: V) -> Option<V> |
| 82 | +/// where K: Hash + Eq |
| 83 | +/// { |
| 84 | +/// # unimplemented!() |
| 85 | +/// // ... |
| 86 | +/// } |
| 87 | +/// |
| 88 | +/// pub fn get<Q>(&self, k: &Q) -> Option<&V> |
| 89 | +/// where |
| 90 | +/// K: Borrow<Q>, |
| 91 | +/// Q: Hash + Eq + ?Sized |
| 92 | +/// { |
| 93 | +/// # unimplemented!() |
| 94 | +/// // ... |
| 95 | +/// } |
| 96 | +/// } |
| 97 | +/// ``` |
| 98 | +/// |
| 99 | +/// The entire hash map is generic over a key type `K`. Because these keys |
| 100 | +/// are stored with the hash map, this type has to own the key’s data. |
| 101 | +/// When inserting a key-value pair, the map is given such a `K` and needs |
| 102 | +/// to find the correct hash bucket and check if the key is already present |
| 103 | +/// based on that `K`. It therefore requires `K: Hash + Eq`. |
| 104 | +/// |
| 105 | +/// When searching for a value in the map, however, having to provide a |
| 106 | +/// reference to a `K` as the key to search for would require to always |
| 107 | +/// create such an owned value. For string keys, this would mean a `String` |
| 108 | +/// value needs to be created just for the search for cases where only a |
| 109 | +/// `str` is available. |
| 110 | +/// |
| 111 | +/// Instead, the `get` method is generic over the type of the underlying key |
| 112 | +/// data, called `Q` in the method signature above. It states that `K` |
| 113 | +/// borrows as a `Q` by requiring that `K: Borrow<Q>`. By additionally |
| 114 | +/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q` |
| 115 | +/// have implementations of the `Hash` and `Eq` traits that produce identical |
| 116 | +/// results. |
| 117 | +/// |
| 118 | +/// The implementation of `get` relies in particular on identical |
| 119 | +/// implementations of `Hash` by determining the key’s hash bucket by calling |
| 120 | +/// `Hash::hash` on the `Q` value even though it inserted the key based on |
| 121 | +/// the hash value calculated from the `K` value. |
| 122 | +/// |
| 123 | +/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value |
| 124 | +/// produces a different hash than `Q`. For instance, imagine you have a |
| 125 | +/// type that wraps a string but compares ASCII letters ignoring their case: |
| 126 | +/// |
| 127 | +/// ``` |
| 128 | +/// pub struct CaseInsensitiveString(String); |
| 129 | +/// |
| 130 | +/// impl PartialEq for CaseInsensitiveString { |
| 131 | +/// fn eq(&self, other: &Self) -> bool { |
| 132 | +/// self.0.eq_ignore_ascii_case(&other.0) |
| 133 | +/// } |
| 134 | +/// } |
| 135 | +/// |
| 136 | +/// impl Eq for CaseInsensitiveString { } |
| 137 | +/// ``` |
| 138 | +/// |
| 139 | +/// Because two equal values need to produce the same hash value, the |
| 140 | +/// implementation of `Hash` needs to ignore ASCII case, too: |
| 141 | +/// |
| 142 | +/// ``` |
| 143 | +/// # use std::hash::{Hash, Hasher}; |
| 144 | +/// # pub struct CaseInsensitiveString(String); |
| 145 | +/// impl Hash for CaseInsensitiveString { |
| 146 | +/// fn hash<H: Hasher>(&self, state: &mut H) { |
| 147 | +/// for c in self.0.as_bytes() { |
| 148 | +/// c.to_ascii_lowercase().hash(state) |
| 149 | +/// } |
| 150 | +/// } |
| 151 | +/// } |
| 152 | +/// ``` |
| 153 | +/// |
| 154 | +/// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can |
| 155 | +/// provide a reference to a string slice via its contained owned string. |
| 156 | +/// But because its `Hash` implementation differs, it behaves differently |
| 157 | +/// from `str` and therefore must not, in fact, implement `Borrow<str>`. |
| 158 | +/// If it wants to allow others access to the underlying `str`, it can do |
| 159 | +/// that via `AsRef<str>` which doesn’t carry any extra requirements. |
| 160 | +/// |
| 161 | +/// [`Hash`]: ../../std/hash/trait.Hash.html |
| 162 | +/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html |
| 163 | +/// [`String`]: ../../std/string/struct.String.html |
| 164 | +/// [`str`]: ../../std/primitive.str.html |
35 | 165 | #[stable(feature = "rust1", since = "1.0.0")]
|
36 | 166 | pub trait Borrow<Borrowed: ?Sized> {
|
37 | 167 | /// Immutably borrows from an owned value.
|
@@ -59,7 +189,11 @@ pub trait Borrow<Borrowed: ?Sized> {
|
59 | 189 |
|
60 | 190 | /// A trait for mutably borrowing data.
|
61 | 191 | ///
|
62 |
| -/// Similar to `Borrow`, but for mutable borrows. |
| 192 | +/// As a companion to [`Borrow<T>`] this trait allows a type to borrow as |
| 193 | +/// an underlying type by providing a mutable reference. See [`Borrow<T>`] |
| 194 | +/// for more information on borrowing as another type. |
| 195 | +/// |
| 196 | +/// [`Borrow<T>`]: trait.Borrow.html |
63 | 197 | #[stable(feature = "rust1", since = "1.0.0")]
|
64 | 198 | pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
|
65 | 199 | /// Mutably borrows from an owned value.
|
|
0 commit comments