]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | //! A module for working with borrowed data. |
2 | ||
3 | #![stable(feature = "rust1", since = "1.0.0")] | |
4 | ||
e9174d1e SL |
5 | /// A trait for borrowing data. |
6 | /// | |
0531ce1d XL |
7 | /// In Rust, it is common to provide different representations of a type for |
8 | /// different use cases. For instance, storage location and management for a | |
9 | /// value can be specifically chosen as appropriate for a particular use via | |
10 | /// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic | |
11 | /// wrappers that can be used with any type, some types provide optional | |
12 | /// facets providing potentially costly functionality. An example for such a | |
13 | /// type is [`String`] which adds the ability to extend a string to the basic | |
14 | /// [`str`]. This requires keeping additional information unnecessary for a | |
15 | /// simple, immutable string. | |
e9174d1e | 16 | /// |
0531ce1d XL |
17 | /// These types provide access to the underlying data through references |
18 | /// to the type of that data. They are said to be ‘borrowed as’ that type. | |
19 | /// For instance, a [`Box<T>`] can be borrowed as `T` while a [`String`] | |
20 | /// can be borrowed as `str`. | |
e9174d1e | 21 | /// |
0531ce1d XL |
22 | /// Types express that they can be borrowed as some type `T` by implementing |
23 | /// `Borrow<T>`, providing a reference to a `T` in the trait’s | |
24 | /// [`borrow`] method. A type is free to borrow as several different types. | |
25 | /// If it wishes to mutably borrow as the type – allowing the underlying data | |
26 | /// to be modified, it can additionally implement [`BorrowMut<T>`]. | |
e9174d1e | 27 | /// |
0531ce1d XL |
28 | /// Further, when providing implementations for additional traits, it needs |
29 | /// to be considered whether they should behave identical to those of the | |
30 | /// underlying type as a consequence of acting as a representation of that | |
31 | /// underlying type. Generic code typically uses `Borrow<T>` when it relies | |
32 | /// on the identical behavior of these additional trait implementations. | |
33 | /// These traits will likely appear as additional trait bounds. | |
e9174d1e | 34 | /// |
532ac7d7 XL |
35 | /// In particular `Eq`, `Ord` and `Hash` must be equivalent for |
36 | /// borrowed and owned values: `x.borrow() == y.borrow()` should give the | |
37 | /// same result as `x == y`. | |
38 | /// | |
0531ce1d XL |
39 | /// If generic code merely needs to work for all types that can |
40 | /// provide a reference to related type `T`, it is often better to use | |
41 | /// [`AsRef<T>`] as more types can safely implement it. | |
42 | /// | |
43 | /// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html | |
44 | /// [`BorrowMut<T>`]: trait.BorrowMut.html | |
45 | /// [`Box<T>`]: ../../std/boxed/struct.Box.html | |
46 | /// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html | |
47 | /// [`Rc<T>`]: ../../std/rc/struct.Rc.html | |
48 | /// [`str`]: ../../std/primitive.str.html | |
49 | /// [`String`]: ../../std/string/struct.String.html | |
50 | /// [`borrow`]: #tymethod.borrow | |
51 | /// | |
52 | /// # Examples | |
53 | /// | |
54 | /// As a data collection, [`HashMap<K, V>`] owns both keys and values. If | |
55 | /// the key’s actual data is wrapped in a managing type of some kind, it | |
56 | /// should, however, still be possible to search for a value using a | |
57 | /// reference to the key’s data. For instance, if the key is a string, then | |
58 | /// it is likely stored with the hash map as a [`String`], while it should | |
59 | /// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to | |
60 | /// operate on a `String` while `get` needs to be able to use a `&str`. | |
61 | /// | |
62 | /// Slightly simplified, the relevant parts of `HashMap<K, V>` look like | |
63 | /// this: | |
64 | /// | |
65 | /// ``` | |
66 | /// use std::borrow::Borrow; | |
67 | /// use std::hash::Hash; | |
68 | /// | |
69 | /// pub struct HashMap<K, V> { | |
70 | /// # marker: ::std::marker::PhantomData<(K, V)>, | |
71 | /// // fields omitted | |
72 | /// } | |
73 | /// | |
74 | /// impl<K, V> HashMap<K, V> { | |
75 | /// pub fn insert(&self, key: K, value: V) -> Option<V> | |
76 | /// where K: Hash + Eq | |
77 | /// { | |
78 | /// # unimplemented!() | |
79 | /// // ... | |
80 | /// } | |
81 | /// | |
82 | /// pub fn get<Q>(&self, k: &Q) -> Option<&V> | |
83 | /// where | |
84 | /// K: Borrow<Q>, | |
85 | /// Q: Hash + Eq + ?Sized | |
86 | /// { | |
87 | /// # unimplemented!() | |
88 | /// // ... | |
89 | /// } | |
90 | /// } | |
91 | /// ``` | |
92 | /// | |
93 | /// The entire hash map is generic over a key type `K`. Because these keys | |
94 | /// are stored with the hash map, this type has to own the key’s data. | |
95 | /// When inserting a key-value pair, the map is given such a `K` and needs | |
96 | /// to find the correct hash bucket and check if the key is already present | |
97 | /// based on that `K`. It therefore requires `K: Hash + Eq`. | |
98 | /// | |
99 | /// When searching for a value in the map, however, having to provide a | |
100 | /// reference to a `K` as the key to search for would require to always | |
101 | /// create such an owned value. For string keys, this would mean a `String` | |
102 | /// value needs to be created just for the search for cases where only a | |
103 | /// `str` is available. | |
104 | /// | |
105 | /// Instead, the `get` method is generic over the type of the underlying key | |
106 | /// data, called `Q` in the method signature above. It states that `K` | |
107 | /// borrows as a `Q` by requiring that `K: Borrow<Q>`. By additionally | |
108 | /// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q` | |
109 | /// have implementations of the `Hash` and `Eq` traits that produce identical | |
110 | /// results. | |
111 | /// | |
112 | /// The implementation of `get` relies in particular on identical | |
113 | /// implementations of `Hash` by determining the key’s hash bucket by calling | |
114 | /// `Hash::hash` on the `Q` value even though it inserted the key based on | |
115 | /// the hash value calculated from the `K` value. | |
116 | /// | |
117 | /// As a consequence, the hash map breaks if a `K` wrapping a `Q` value | |
118 | /// produces a different hash than `Q`. For instance, imagine you have a | |
119 | /// type that wraps a string but compares ASCII letters ignoring their case: | |
120 | /// | |
121 | /// ``` | |
122 | /// pub struct CaseInsensitiveString(String); | |
123 | /// | |
124 | /// impl PartialEq for CaseInsensitiveString { | |
125 | /// fn eq(&self, other: &Self) -> bool { | |
126 | /// self.0.eq_ignore_ascii_case(&other.0) | |
127 | /// } | |
128 | /// } | |
129 | /// | |
130 | /// impl Eq for CaseInsensitiveString { } | |
131 | /// ``` | |
132 | /// | |
133 | /// Because two equal values need to produce the same hash value, the | |
134 | /// implementation of `Hash` needs to ignore ASCII case, too: | |
135 | /// | |
136 | /// ``` | |
137 | /// # use std::hash::{Hash, Hasher}; | |
138 | /// # pub struct CaseInsensitiveString(String); | |
139 | /// impl Hash for CaseInsensitiveString { | |
140 | /// fn hash<H: Hasher>(&self, state: &mut H) { | |
141 | /// for c in self.0.as_bytes() { | |
142 | /// c.to_ascii_lowercase().hash(state) | |
143 | /// } | |
144 | /// } | |
145 | /// } | |
146 | /// ``` | |
147 | /// | |
148 | /// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can | |
149 | /// provide a reference to a string slice via its contained owned string. | |
150 | /// But because its `Hash` implementation differs, it behaves differently | |
151 | /// from `str` and therefore must not, in fact, implement `Borrow<str>`. | |
152 | /// If it wants to allow others access to the underlying `str`, it can do | |
153 | /// that via `AsRef<str>` which doesn’t carry any extra requirements. | |
154 | /// | |
155 | /// [`Hash`]: ../../std/hash/trait.Hash.html | |
156 | /// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html | |
157 | /// [`String`]: ../../std/string/struct.String.html | |
158 | /// [`str`]: ../../std/primitive.str.html | |
e9174d1e SL |
159 | #[stable(feature = "rust1", since = "1.0.0")] |
160 | pub trait Borrow<Borrowed: ?Sized> { | |
161 | /// Immutably borrows from an owned value. | |
162 | /// | |
163 | /// # Examples | |
164 | /// | |
165 | /// ``` | |
166 | /// use std::borrow::Borrow; | |
167 | /// | |
168 | /// fn check<T: Borrow<str>>(s: T) { | |
169 | /// assert_eq!("Hello", s.borrow()); | |
170 | /// } | |
171 | /// | |
172 | /// let s = "Hello".to_string(); | |
173 | /// | |
174 | /// check(s); | |
175 | /// | |
176 | /// let s = "Hello"; | |
177 | /// | |
178 | /// check(s); | |
179 | /// ``` | |
180 | #[stable(feature = "rust1", since = "1.0.0")] | |
181 | fn borrow(&self) -> &Borrowed; | |
182 | } | |
183 | ||
184 | /// A trait for mutably borrowing data. | |
185 | /// | |
0531ce1d XL |
186 | /// As a companion to [`Borrow<T>`] this trait allows a type to borrow as |
187 | /// an underlying type by providing a mutable reference. See [`Borrow<T>`] | |
188 | /// for more information on borrowing as another type. | |
189 | /// | |
190 | /// [`Borrow<T>`]: trait.Borrow.html | |
e9174d1e | 191 | #[stable(feature = "rust1", since = "1.0.0")] |
dfeec247 | 192 | pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> { |
e9174d1e SL |
193 | /// Mutably borrows from an owned value. |
194 | /// | |
195 | /// # Examples | |
196 | /// | |
197 | /// ``` | |
198 | /// use std::borrow::BorrowMut; | |
199 | /// | |
200 | /// fn check<T: BorrowMut<[i32]>>(mut v: T) { | |
201 | /// assert_eq!(&mut [1, 2, 3], v.borrow_mut()); | |
202 | /// } | |
203 | /// | |
204 | /// let v = vec![1, 2, 3]; | |
205 | /// | |
206 | /// check(v); | |
207 | /// ``` | |
208 | #[stable(feature = "rust1", since = "1.0.0")] | |
209 | fn borrow_mut(&mut self) -> &mut Borrowed; | |
210 | } | |
211 | ||
212 | #[stable(feature = "rust1", since = "1.0.0")] | |
213 | impl<T: ?Sized> Borrow<T> for T { | |
dfeec247 XL |
214 | fn borrow(&self) -> &T { |
215 | self | |
216 | } | |
e9174d1e SL |
217 | } |
218 | ||
219 | #[stable(feature = "rust1", since = "1.0.0")] | |
220 | impl<T: ?Sized> BorrowMut<T> for T { | |
dfeec247 XL |
221 | fn borrow_mut(&mut self) -> &mut T { |
222 | self | |
223 | } | |
e9174d1e SL |
224 | } |
225 | ||
226 | #[stable(feature = "rust1", since = "1.0.0")] | |
0bf4aa26 | 227 | impl<T: ?Sized> Borrow<T> for &T { |
dfeec247 XL |
228 | fn borrow(&self) -> &T { |
229 | &**self | |
230 | } | |
e9174d1e SL |
231 | } |
232 | ||
233 | #[stable(feature = "rust1", since = "1.0.0")] | |
0bf4aa26 | 234 | impl<T: ?Sized> Borrow<T> for &mut T { |
dfeec247 XL |
235 | fn borrow(&self) -> &T { |
236 | &**self | |
237 | } | |
e9174d1e SL |
238 | } |
239 | ||
240 | #[stable(feature = "rust1", since = "1.0.0")] | |
0bf4aa26 | 241 | impl<T: ?Sized> BorrowMut<T> for &mut T { |
dfeec247 XL |
242 | fn borrow_mut(&mut self) -> &mut T { |
243 | &mut **self | |
244 | } | |
e9174d1e | 245 | } |