1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
//! 用于处理借用数据的模块。 #![stable(feature = "rust1", since = "1.0.0")] /// 借用数据的 trait。 /// /// 在 Rust 中,通常为不同的用例提供类型的不同表示形式。 /// 例如,可以通过指针类型 (例如 [`Box<T>`] 或 [`Rc<T>`]) 为特定用途适当地选择值的存储位置和管理。 /// 除了这些可以与任何类型一起使用的泛型包装之外,某些类型还提供了可选的构面,从而提供了可能昂贵的功能。 /// 这种类型的一个示例是 [`String`],它增加了将字符串扩展到基本 [`str`] 的功能。 /// 这要求保持简单的不可变字符串不需要的其他信息。 /// /// 这些类型通过引用该数据的类型来提供对基础数据的访问。据说它们是借来的那种类型的。 /// 例如,可以将 [`Box<T>`] 作为 `T` 借用,而可以将 [`String`] 作为 `str` 借用。 /// /// 类型表示可以通过实现 `Borrow<T>` 来借用它们作为某种类型的 `T`,并在 trait 的 [`borrow`] 方法中对 `T` 进行引用。一个类型可以自由借用为几种不同的类型。 /// 如果希望将类型可变为借用-允许修改基础数据,则可以另外实现 [`BorrowMut<T>`]。 /// /// 此外,在为其他 traits 提供实现时,需要考虑由于充当该基础类型的表示而导致它们的行为是否与基础类型的行为相同。 /// 当泛型代码依赖于这些其他 trait 实现的相同行为时,通常会使用 `Borrow<T>`。 /// 这些 traits 可能会显示为其他 trait bounds。 /// /// 特别是对于借用和拥有的值,`Eq`,`Ord` 和 `Hash` 必须等效: `x.borrow() == y.borrow()` 的结果应与 `x == y` 相同。 /// /// 如果泛型代码只需要为可以为相关类型 `T` 提供引用的所有类型工作,则通常最好使用 [`AsRef<T>`],因为更多类型可以安全地实现它。 /// /// [`Box<T>`]: ../../std/boxed/struct.Box.html /// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html /// [`Rc<T>`]: ../../std/rc/struct.Rc.html /// [`String`]: ../../std/string/struct.String.html /// [`borrow`]: Borrow::borrow /// /// # Examples /// /// 作为数据集合,[`HashMap<K, V>`] 同时拥有键和值。如果键的实际数据包装在某种管理类型中,则仍然应该可以使用对键数据的引用来搜索值。 /// 例如,如果键是一个字符串,则它很可能与哈希 map 一起存储为 [`String`],而应该可以使用 [`&str`][`str`] 进行搜索。 /// 因此,`insert` 需要在 `String` 上运行,而 `get` 需要能够使用 `&str`。 /// /// 略有简化,`HashMap<K, V>` 的相关部分如下所示: /// /// ``` /// use std::borrow::Borrow; /// use std::hash::Hash; /// /// pub struct HashMap<K, V> { /// # marker: ::std::marker::PhantomData<(K, V)>, /// // 字段省略 /// } /// /// impl<K, V> HashMap<K, V> { /// pub fn insert(&self, key: K, value: V) -> Option<V> /// where K: Hash + Eq /// { /// # unimplemented!() /// // ... /// } /// /// pub fn get<Q>(&self, k: &Q) -> Option<&V> /// where /// K: Borrow<Q>, /// Q: Hash + Eq + ?Sized /// { /// # unimplemented!() /// // ... /// } /// } /// ``` /// /// 整个哈希 map 在键类型 `K` 上是泛型的。由于这些键存储在哈希 map 中,因此该类型必须拥有键的数据。 /// 插入键值对时,会给 map 这样的 `K`,并且需要找到正确的哈希值存储区,并根据该 `K` 检查键是否已存在。因此,它需要 `K: Hash + Eq`。 /// /// 但是,在 map 中搜索值时,必须提供 `K` 的引用作为搜索键,这要求始终创建此类拥有的值。 /// 对于字符串键,这意味着仅在搜索仅 `str` 可用的情况下,才需要创建 `String` 值。 /// /// 相反,`get` 方法是基础键数据类型的泛型,在上面的方法签名中称为 `Q`。它通过要求 `K: Borrow<Q>` 来声明 `K` 借用为 `Q`。 /// 通过额外要求 `Q: Hash + Eq`,它表示要求 `K` 和 `Q` 具有 `Hash` 和 `Eq` traits 的实现,它们会产生相同的结果。 /// /// `get` 的实现尤其依赖于 `Hash` 的相同实现,即通过基于 `Q` 值计算出的哈希值插入键,通过在 `Q` 值上调用 `Hash::hash` 来确定键的哈希存储桶。 /// /// /// 结果,如果包装了 `Q` 值的 `K` 产生与 `Q` 不同的哈希,则哈希 map 会中断。例如,假设您有一个包裹字符串但比较 ASCII 字母而忽略大小写的类型: /// /// ``` /// pub struct CaseInsensitiveString(String); /// /// impl PartialEq for CaseInsensitiveString { /// fn eq(&self, other: &Self) -> bool { /// self.0.eq_ignore_ascii_case(&other.0) /// } /// } /// /// impl Eq for CaseInsensitiveString { } /// ``` /// /// 因为两个相等的值需要产生相同的哈希值,所以 `Hash` 的实现也需要忽略 ASCII 大小写: /// /// ``` /// # use std::hash::{Hash, Hasher}; /// # pub struct CaseInsensitiveString(String); /// impl Hash for CaseInsensitiveString { /// fn hash<H: Hasher>(&self, state: &mut H) { /// for c in self.0.as_bytes() { /// c.to_ascii_lowercase().hash(state) /// } /// } /// } /// ``` /// /// `CaseInsensitiveString` 可以实现 `Borrow<str>` 吗? 它当然可以通过其包含的拥有的字符串为字符串片段提供引用。 /// 但是由于 `Hash` 的实现方式不同,所以它的行为与 `str` 不同,因此,实际上,一定不能实现 `Borrow<str>`。 /// 如果它希望允许其他人访问基础 `str`,则可以通过 `AsRef<str>` 来实现,而 `AsRef<str>` 则没有任何额外的要求。 /// /// [`Hash`]: crate::hash::Hash /// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html /// [`String`]: ../../std/string/struct.String.html /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Borrow"] pub trait Borrow<Borrowed: ?Sized> { /// 从拥有的值中一成不变地借用。 /// /// # Examples /// /// ``` /// use std::borrow::Borrow; /// /// fn check<T: Borrow<str>>(s: T) { /// assert_eq!("Hello", s.borrow()); /// } /// /// let s = "Hello".to_string(); /// /// check(s); /// /// let s = "Hello"; /// /// check(s); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn borrow(&self) -> &Borrowed; } /// 用于可变借用数据的 trait。 /// /// 作为 [`Borrow<T>`] 的伴侣,此 trait 通过提供变量引用允许类型借用作为基础类型。 /// 请参见 [`Borrow<T>`],以了解更多有关借用另一种类型的信息。 /// #[stable(feature = "rust1", since = "1.0.0")] pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> { /// 从拥有的值中借用。 /// /// # Examples /// /// ``` /// use std::borrow::BorrowMut; /// /// fn check<T: BorrowMut<[i32]>>(mut v: T) { /// assert_eq!(&mut [1, 2, 3], v.borrow_mut()); /// } /// /// let v = vec![1, 2, 3]; /// /// check(v); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn borrow_mut(&mut self) -> &mut Borrowed; } #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Borrow<T> for T { #[rustc_diagnostic_item = "noop_method_borrow"] fn borrow(&self) -> &T { self } } #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> BorrowMut<T> for T { fn borrow_mut(&mut self) -> &mut T { self } } #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Borrow<T> for &T { fn borrow(&self) -> &T { &**self } } #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Borrow<T> for &mut T { fn borrow(&self) -> &T { &**self } } #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> BorrowMut<T> for &mut T { fn borrow_mut(&mut self) -> &mut T { &mut **self } }