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 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
use crate::ops::ControlFlow; /// `?` 运算符和 `try {}` 块。 /// /// `try_*` 方法通常涉及实现此 trait 的类型。例如,传递给 [`Iterator::try_fold`] 和 [`Iterator::try_for_each`] 的闭包必须返回这样的类型。 /// /// `Try` 类型通常是那些包含两个或更多类别值的类型,其中一些子集通常通过早期返回处理,因此值得提供一个简洁 (但仍然可见) 的语法来简化它。 /// /// /// 这在 [`Result`] 和 [`Option`] 的错误处理中最常见。 /// 这个 trait 的典型实现是在 [`ControlFlow`] 上。 /// /// # 在泛型代码中使用 `Try` /// /// `Iterator::try_fold` 在 Rust 1.27 中稳定到调用,但是这个 trait 更新了很多。为了说明各种关联类型和方法,让我们实现我们自己的版本。 /// /// 提醒一下,一个可靠的折叠版本看起来像这样: /// /// ``` /// fn simple_fold<A, T>( /// iter: impl Iterator<Item = T>, /// mut accum: A, /// mut f: impl FnMut(A, T) -> A, /// ) -> A { /// for x in iter { /// accum = f(accum, x); /// } /// accum /// } /// ``` /// /// 因此,不是 `f` 只返回一个 `A`,我们需要它返回一些在不要短路路径中产生一个 `A` 的其他类型。 /// 方便的是,这也是我们需要从函数返回的类型。 /// /// 让我们为该类型添加一个新的泛型参数 `R`,并将其绑定到我们想要的输出类型: /// /// ``` /// # #![feature(try_trait_v2)] /// # use std::ops::Try; /// fn simple_try_fold_1<A, T, R: Try<Output = A>>( /// iter: impl Iterator<Item = T>, /// mut accum: A, /// mut f: impl FnMut(A, T) -> R, /// ) -> R { /// todo!() /// } /// ``` /// /// 如果我们遍历整个迭代器,我们需要使用 [`Try::from_output`] 将累加器包装成返回类型: /// /// ``` /// # #![feature(try_trait_v2)] /// # use std::ops::{ControlFlow, Try}; /// fn simple_try_fold_2<A, T, R: Try<Output = A>>( /// iter: impl Iterator<Item = T>, /// mut accum: A, /// mut f: impl FnMut(A, T) -> R, /// ) -> R { /// for x in iter { /// let cf = f(accum, x).branch(); /// match cf { /// ControlFlow::Continue(a) => accum = a, /// ControlFlow::Break(_) => todo!(), /// } /// } /// R::from_output(accum) /// } /// ``` /// /// 我们还需要 [`FromResidual::from_residual`] 将 residual 恢复为原始类型。但因为它是 `Try` 的一个 super trait,所以我们不必在界限内提及它。 /// 所有实现 `Try` 的类型都可以从它们对应的 residual 中重新创建,所以我们将调用它: /// /// ``` /// # #![feature(try_trait_v2)] /// # use std::ops::{ControlFlow, Try}; /// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>( /// iter: impl Iterator<Item = T>, /// mut accum: A, /// mut f: impl FnMut(A, T) -> R, /// ) -> R { /// for x in iter { /// let cf = f(accum, x).branch(); /// match cf { /// ControlFlow::Continue(a) => accum = a, /// ControlFlow::Break(r) => return R::from_residual(r), /// } /// } /// R::from_output(accum) /// } /// ``` /// /// 但是这个 "调用`branch`,然后在它上面进行 `match`,如果它是 `Break`,则 `return`" 正是在 `?` 操作符内部发生的事情。因此,我们可以使用 `?` 代替手动完成所有这些操作: /// /// ``` /// # #![feature(try_trait_v2)] /// # use std::ops::Try; /// fn simple_try_fold<A, T, R: Try<Output = A>>( /// iter: impl Iterator<Item = T>, /// mut accum: A, /// mut f: impl FnMut(A, T) -> R, /// ) -> R { /// for x in iter { /// accum = f(accum, x)?; /// } /// R::from_output(accum) /// } /// ``` /// /// /// /// /// /// /// #[unstable(feature = "try_trait_v2", issue = "84277")] #[rustc_on_unimplemented( on( all(from_method = "from_output", from_desugaring = "TryBlock"), message = "a `try` block must return `Result` or `Option` \ (or another type that implements `{Try}`)", label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`", ), on( all(from_method = "branch", from_desugaring = "QuestionMark"), message = "the `?` operator can only be applied to values \ that implement `{Try}`", label = "the `?` operator cannot be applied to type `{Self}`" ) )] #[doc(alias = "?")] #[lang = "Try"] pub trait Try: FromResidual { /// 当不短路时,`?` 产生的值的类型。 #[unstable(feature = "try_trait_v2", issue = "84277")] type Output; /// 短路时作为 `?` 的一部分传递给 [`FromResidual::from_residual`] 的值的类型。 /// /// 这表示 `Self` 类型的可能值,而不是 `Output` 类型所表示的值。 /// /// # 实现者注意 /// /// 这种类型的选择对于相互转化至关重要。 /// 与 `Output` 类型不同,它通常是原始泛型类型,这种类型通常是某种类型的 newtype 到 "color" 类型,以便与其他类型的 residual 区别开来。 /// /// 这就是为什么 `Result<T, E>::Residual` 不是 `E`,而是 `Result<Infallible, E>`。 /// 例如,这样它就不同于 `ControlFlow<E>::Residual`,因此 `ControlFlow` 上的 `?` 不能用于返回 `Result` 的方法中。 /// /// 如果您正在创建实现 `Try<Output = T>` 的泛型 `Foo<T>`,那么通常您可以使用 `Foo<std::convert::Infallible>` 作为它的 `Residual` 类型: 该类型将在正确位置有一个 "hole",并将保留 residual 的 "foo-ness",因此其他类型需要选择加入到相互转换中。 /// /// /// /// /// /// /// /// #[unstable(feature = "try_trait_v2", issue = "84277")] type Residual; /// 从它的 `Output` 类型构造类型。 /// /// 这应该与 `branch` 方法一致实现,以便应用 `?` 运算符将返回原始值: `Try::from_output(x).branch() --> ControlFlow::Continue(x)`. /// /// /// # Examples /// /// ``` /// #![feature(try_trait_v2)] /// use std::ops::Try; /// /// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3)); /// assert_eq!(<Option<_> as Try>::from_output(4), Some(4)); /// assert_eq!( /// <std::ops::ControlFlow<String, _> as Try>::from_output(5), /// std::ops::ControlFlow::Continue(5), /// ); /// /// # fn make_question_mark_work() -> Option<()> { /// assert_eq!(Option::from_output(4)?, 4); /// # None } /// # make_question_mark_work(); /// /// // 例如,这用于 `try_fold` 中的累加器: /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() }); /// assert_eq!(r, Some(4)); /// ``` /// #[lang = "from_output"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_output(output: Self::Output) -> Self; /// 在 `?` 来决定操作符是应该生成一个值 (因为它返回了 [`ControlFlow::Continue`]),还是将一个值传播回调用者(因为它返回了 [`ControlFlow::Break`])。 /// /// /// # Examples /// /// ``` /// #![feature(try_trait_v2)] /// use std::ops::{ControlFlow, Try}; /// /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3)); /// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3))); /// /// assert_eq!(Some(3).branch(), ControlFlow::Continue(3)); /// assert_eq!(None::<String>.branch(), ControlFlow::Break(None)); /// /// assert_eq!(ControlFlow::<String, _>::Continue(3).branch(), ControlFlow::Continue(3)); /// assert_eq!( /// ControlFlow::<_, String>::Break(3).branch(), /// ControlFlow::Break(ControlFlow::Break(3)), /// ); /// ``` /// /// #[lang = "branch"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; } /// 用于指定哪些残差可以转换为哪些 [`crate::ops::Try`] 类型。 /// /// 每个 `Try` 类型都需要从它自己关联的 `Residual` 类型重新创建,但也可以有额外的 `FromResidual` 实现来支持与其他 `Try` 类型的相互转换。 /// /// #[rustc_on_unimplemented( on( all( from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::result::Result<T, E>", R = "std::option::Option<std::convert::Infallible>" ), message = "the `?` operator can only be used on `Result`s, not `Option`s, \ in {ItemContext} that returns `Result`", label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`", enclosing_scope = "this function returns a `Result`" ), on( all( from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::result::Result<T, E>", ), // 在 `?` 中 `From` 的 trait 选择代码中有一条特殊的错误消息,因此对于结果中的错误没有显示,因此它可以比 `ControlFlow` 更强烈地表达。 // // message = "the `?` operator can only be used on `Result`s \ in {ItemContext} that returns `Result`", label = "this `?` produces `{R}`, which is incompatible with `{Self}`", enclosing_scope = "this function returns a `Result`" ), on( all( from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::option::Option<T>", R = "std::result::Result<T, E>", ), message = "the `?` operator can only be used on `Option`s, not `Result`s, \ in {ItemContext} that returns `Option`", label = "use `.ok()?` if you want to discard the `{R}` error information", enclosing_scope = "this function returns an `Option`" ), on( all( from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::option::Option<T>", ), // `Option`-in-`Option` 总是有效,因为只有一种可能的残差,所以这也可以用强烈的措辞表达。 // message = "the `?` operator can only be used on `Option`s \ in {ItemContext} that returns `Option`", label = "this `?` produces `{R}`, which is incompatible with `{Self}`", enclosing_scope = "this function returns an `Option`" ), on( all( from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::ops::ControlFlow<B, C>", R = "std::ops::ControlFlow<B, C>", ), message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \ can only be used on other `ControlFlow<B, _>`s (with the same Break type)", label = "this `?` produces `{R}`, which is incompatible with `{Self}`", enclosing_scope = "this function returns a `ControlFlow`", note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`" ), on( all( from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::ops::ControlFlow<B, C>", // `R` 不是 `ControlFlow`,正如前面匹配的那样 ), message = "the `?` operator can only be used on `ControlFlow`s \ in {ItemContext} that returns `ControlFlow`", label = "this `?` produces `{R}`, which is incompatible with `{Self}`", enclosing_scope = "this function returns a `ControlFlow`", ), on( all( from_method = "from_residual", from_desugaring = "QuestionMark" ), message = "the `?` operator can only be used in {ItemContext} \ that returns `Result` or `Option` \ (or another type that implements `{FromResidual}`)", label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", enclosing_scope = "this function should return `Result` or `Option` to accept `?`" ), )] #[unstable(feature = "try_trait_v2", issue = "84277")] pub trait FromResidual<R = <Self as Try>::Residual> { /// 从兼容的 `Residual` 类型构造类型。 /// /// 这应该与 `branch` 方法一致地实现,以便应用 `?` 运算符将得到等效的 residual: `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`. /// /// (当涉及到相互转换时,它可能不是一个相同的 residual。) /// /// # Examples /// /// ``` /// #![feature(try_trait_v2)] /// use std::ops::{ControlFlow, FromResidual}; /// /// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3)); /// assert_eq!(Option::<String>::from_residual(None), None); /// assert_eq!( /// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)), /// ControlFlow::Break(5), /// ); /// ``` /// #[lang = "from_residual"] #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_residual(residual: R) -> Self; }