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` 方法一致地实现,以便应用 `?` 运算符将返回等效的残差: `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`。
    ///
    /// (当涉及相互转换时,它不能是*相同的*残差。)
    ///
    /// # 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;
}