|
17 | 17 | /// In Rust, it is common to provide different representations of a type for
|
18 | 18 | /// different use cases. For instance, storage location and management for a
|
19 | 19 | /// value can be specifically chosen as appropriate for a particular use via
|
20 |
| -/// pointer types such as [`Box<T>`] or [`Rc<T>`] or one can opt into |
21 |
| -/// concurrency via synchronization types such as [`Mutex<T>`], avoiding the |
22 |
| -/// associated cost when in parallel doesn’t happen. Beyond these generic |
| 20 | +/// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic |
23 | 21 | /// wrappers that can be used with any type, some types provide optional
|
24 | 22 | /// facets providing potentially costly functionality. An example for such a
|
25 | 23 | /// type is [`String`] which adds the ability to extend a string to the basic
|
26 | 24 | /// [`str`]. This requires keeping additional information unnecessary for a
|
27 |
| -/// simple, imutable string. |
| 25 | +/// simple, immutable string. |
28 | 26 | ///
|
29 | 27 | /// These types signal that they are a specialized representation of a basic
|
30 | 28 | /// type `T` by implementing `Borrow<T>`. The method `borrow` provides a way
|
31 |
| -/// to convert a reference to the type into a reference to the underlying |
32 |
| -/// basic type. |
| 29 | +/// to convert a reference to the type into a reference to this basic type |
| 30 | +/// `T`. |
33 | 31 | ///
|
34 |
| -/// If a type implementing `Borrow<T>` implements other traits also |
35 |
| -/// implemented by `T`, these implementations behave identically if the trait |
36 |
| -/// is concerned with the data rather than its representation. For instance, |
37 |
| -/// the comparison traits such as `PartialEq` or `PartialOrd` must behave |
38 |
| -/// identical for `T` and any type implemeting `Borrow<T>`. |
| 32 | +/// Further, when providing implementations for additional traits, it needs |
| 33 | +/// to be considered whether they should behave identical to those of the |
| 34 | +/// underlying type as a consequence of acting as a representation of that |
| 35 | +/// underlying type. |
39 | 36 | ///
|
40 |
| -/// When writing generic code, a use of `Borrow` should always be justified |
41 |
| -/// by additional trait bounds, making it clear that the two types need to |
42 |
| -/// behave identically in a certain context. If the code should merely be |
43 |
| -/// able to operate on any type that can produce a reference to a given type, |
44 |
| -/// you should use [`AsRef`] instead. |
| 37 | +/// Generic code typically uses `Borrow<T>` when it not only needs access |
| 38 | +/// to a reference of the underlying type but relies on the identical |
| 39 | +/// behavior of these additional trait implementations. These traits are |
| 40 | +/// likely to appear as additional trait bounds. |
45 | 41 | ///
|
46 |
| -/// The companion trait [`BorrowMut`] provides the same guarantees for |
47 |
| -/// mutable references. |
| 42 | +/// If generic code merely needs to work for all types that can |
| 43 | +/// provide a reference to related type `T`, it is often better to use |
| 44 | +/// [`AsRef<T>`] as more types can safely implement it. |
48 | 45 | ///
|
49 |
| -/// [`AsRef`]: ../../std/convert/trait.AsRef.html |
| 46 | +/// If a type implementing `Borrow<T>` also wishes to allow mutable access |
| 47 | +/// to the underlying type `T`, it can do so by implementing the companion |
| 48 | +/// trait [`BorrowMut`]. |
| 49 | +/// |
| 50 | +/// Note also that it is perfectly fine for a single type to have multiple |
| 51 | +/// implementations of `Borrow<T>` for different `T`s. In fact, a blanket |
| 52 | +/// implementation lets every type be at least a borrow of itself. |
| 53 | +/// |
| 54 | +/// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html |
50 | 55 | /// [`BorrowMut`]: trait.BorrowMut.html
|
51 | 56 | /// [`Box<T>`]: ../../std/boxed/struct.Box.html
|
52 | 57 | /// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
|
|
111 | 116 | /// data, called `Q` in the method signature above. It states that `K` is a
|
112 | 117 | /// representation of `Q` by requiring that `K: Borrow<Q>`. By additionally
|
113 | 118 | /// requiring `Q: Hash + Eq`, it demands that `K` and `Q` have
|
114 |
| -/// implementations of the `Hash` and `Eq` traits that procude identical |
| 119 | +/// implementations of the `Hash` and `Eq` traits that produce identical |
115 | 120 | /// results.
|
116 | 121 | ///
|
117 | 122 | /// The implementation of `get` relies in particular on identical
|
|
124 | 129 | /// type that wraps a string but compares ASCII letters ignoring their case:
|
125 | 130 | ///
|
126 | 131 | /// ```
|
127 |
| -/// pub struct CIString(String); |
| 132 | +/// pub struct CaseInsensitiveString(String); |
128 | 133 | ///
|
129 |
| -/// impl PartialEq for CIString { |
| 134 | +/// impl PartialEq for CaseInsensitiveString { |
130 | 135 | /// fn eq(&self, other: &Self) -> bool {
|
131 | 136 | /// self.0.eq_ignore_ascii_case(&other.0)
|
132 | 137 | /// }
|
133 | 138 | /// }
|
134 | 139 | ///
|
135 |
| -/// impl Eq for CIString { } |
| 140 | +/// impl Eq for CaseInsensitiveString { } |
136 | 141 | /// ```
|
137 | 142 | ///
|
138 | 143 | /// Because two equal values need to produce the same hash value, the
|
139 | 144 | /// implementation of `Hash` needs to reflect that, too:
|
140 | 145 | ///
|
141 | 146 | /// ```
|
142 | 147 | /// # use std::hash::{Hash, Hasher};
|
143 |
| -/// # pub struct CIString(String); |
144 |
| -/// impl Hash for CIString { |
| 148 | +/// # pub struct CaseInsensitiveString(String); |
| 149 | +/// impl Hash for CaseInsensitiveString { |
145 | 150 | /// fn hash<H: Hasher>(&self, state: &mut H) {
|
146 | 151 | /// for c in self.0.as_bytes() {
|
147 | 152 | /// c.to_ascii_lowercase().hash(state)
|
|
150 | 155 | /// }
|
151 | 156 | /// ```
|
152 | 157 | ///
|
153 |
| -/// Can `CIString` implement `Borrow<str>`? It certainly can provide a |
154 |
| -/// reference to a string slice via its contained owned string. But because |
155 |
| -/// its `Hash` implementation differs, it cannot fulfill the guarantee for |
156 |
| -/// `Borrow` that all common trait implementations must behave the same way |
157 |
| -/// and must not, in fact, implement `Borrow<str>`. If it wants to allow |
158 |
| -/// others access to the underlying `str`, it can do that via `AsRef<str>` |
159 |
| -/// which doesn’t carry any such restrictions. |
| 158 | +/// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can |
| 159 | +/// provide a reference to a string slice via its contained owned string. |
| 160 | +/// But because its `Hash` implementation differs, it behaves differently |
| 161 | +/// from `str` and therefore must not, in fact, implement `Borrow<str>`. |
| 162 | +/// If it wants to allow others access to the underlying `str`, it can do |
| 163 | +/// that via `AsRef<str>` which doesn’t carry any extra requirements. |
160 | 164 | ///
|
161 | 165 | /// [`Hash`]: ../../std/hash/trait.Hash.html
|
162 | 166 | /// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
|
|
0 commit comments