1
use crate::ops::ControlFlow;
2

            
3
/// The `?` operator and `try {}` blocks.
4
///
5
/// `try_*` methods typically involve a type implementing this trait.  For
6
/// example, the closures passed to [`Iterator::try_fold`] and
7
/// [`Iterator::try_for_each`] must return such a type.
8
///
9
/// `Try` types are typically those containing two or more categories of values,
10
/// some subset of which are so commonly handled via early returns that it's
11
/// worth providing a terse (but still visible) syntax to make that easy.
12
///
13
/// This is most often seen for error handling with [`Result`] and [`Option`].
14
/// The quintessential implementation of this trait is on [`ControlFlow`].
15
///
16
/// # Using `Try` in Generic Code
17
///
18
/// `Iterator::try_fold` was stabilized to call back in Rust 1.27, but
19
/// this trait is much newer.  To illustrate the various associated types and
20
/// methods, let's implement our own version.
21
///
22
/// As a reminder, an infallible version of a fold looks something like this:
23
/// ```
24
/// fn simple_fold<A, T>(
25
///     iter: impl Iterator<Item = T>,
26
///     mut accum: A,
27
///     mut f: impl FnMut(A, T) -> A,
28
/// ) -> A {
29
///     for x in iter {
30
///         accum = f(accum, x);
31
///     }
32
///     accum
33
/// }
34
/// ```
35
///
36
/// So instead of `f` returning just an `A`, we'll need it to return some other
37
/// type that produces an `A` in the "don't short circuit" path.  Conveniently,
38
/// that's also the type we need to return from the function.
39
///
40
/// Let's add a new generic parameter `R` for that type, and bound it to the
41
/// output type that we want:
42
/// ```
43
/// # #![feature(try_trait_v2)]
44
/// # use std::ops::Try;
45
/// fn simple_try_fold_1<A, T, R: Try<Output = A>>(
46
///     iter: impl Iterator<Item = T>,
47
///     mut accum: A,
48
///     mut f: impl FnMut(A, T) -> R,
49
/// ) -> R {
50
///     todo!()
51
/// }
52
/// ```
53
///
54
/// If we get through the entire iterator, we need to wrap up the accumulator
55
/// into the return type using [`Try::from_output`]:
56
/// ```
57
/// # #![feature(try_trait_v2)]
58
/// # use std::ops::{ControlFlow, Try};
59
/// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
60
///     iter: impl Iterator<Item = T>,
61
///     mut accum: A,
62
///     mut f: impl FnMut(A, T) -> R,
63
/// ) -> R {
64
///     for x in iter {
65
///         let cf = f(accum, x).branch();
66
///         match cf {
67
///             ControlFlow::Continue(a) => accum = a,
68
///             ControlFlow::Break(_) => todo!(),
69
///         }
70
///     }
71
///     R::from_output(accum)
72
/// }
73
/// ```
74
///
75
/// We'll also need [`FromResidual::from_residual`] to turn the residual back
76
/// into the original type.  But because it's a supertrait of `Try`, we don't
77
/// need to mention it in the bounds.  All types which implement `Try` can be
78
/// recreated from their corresponding residual, so we'll just call it:
79
/// ```
80
/// # #![feature(try_trait_v2)]
81
/// # use std::ops::{ControlFlow, Try};
82
/// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
83
///     iter: impl Iterator<Item = T>,
84
///     mut accum: A,
85
///     mut f: impl FnMut(A, T) -> R,
86
/// ) -> R {
87
///     for x in iter {
88
///         let cf = f(accum, x).branch();
89
///         match cf {
90
///             ControlFlow::Continue(a) => accum = a,
91
///             ControlFlow::Break(r) => return R::from_residual(r),
92
///         }
93
///     }
94
///     R::from_output(accum)
95
/// }
96
/// ```
97
///
98
/// But this "call `branch`, then `match` on it, and `return` if it was a
99
/// `Break`" is exactly what happens inside the `?` operator.  So rather than
100
/// do all this manually, we can just use `?` instead:
101
/// ```
102
/// # #![feature(try_trait_v2)]
103
/// # use std::ops::Try;
104
/// fn simple_try_fold<A, T, R: Try<Output = A>>(
105
///     iter: impl Iterator<Item = T>,
106
///     mut accum: A,
107
///     mut f: impl FnMut(A, T) -> R,
108
/// ) -> R {
109
///     for x in iter {
110
///         accum = f(accum, x)?;
111
///     }
112
///     R::from_output(accum)
113
/// }
114
/// ```
115
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
116
#[rustc_on_unimplemented(
117
    on(
118
        all(from_desugaring = "TryBlock"),
119
        message = "a `try` block must return `Result` or `Option` \
120
                    (or another type that implements `{This}`)",
121
        label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`",
122
    ),
123
    on(
124
        all(from_desugaring = "QuestionMark"),
125
        message = "the `?` operator can only be applied to values that implement `{This}`",
126
        label = "the `?` operator cannot be applied to type `{Self}`"
127
    )
128
)]
129
#[doc(alias = "?")]
130
#[lang = "Try"]
131
#[const_trait]
132
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
133
pub trait Try: [const] FromResidual {
134
    /// The type of the value produced by `?` when *not* short-circuiting.
135
    #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
136
    type Output;
137

            
138
    /// The type of the value passed to [`FromResidual::from_residual`]
139
    /// as part of `?` when short-circuiting.
140
    ///
141
    /// This represents the possible values of the `Self` type which are *not*
142
    /// represented by the `Output` type.
143
    ///
144
    /// # Note to Implementors
145
    ///
146
    /// The choice of this type is critical to interconversion.
147
    /// Unlike the `Output` type, which will often be a raw generic type,
148
    /// this type is typically a newtype of some sort to "color" the type
149
    /// so that it's distinguishable from the residuals of other types.
150
    ///
151
    /// This is why `Result<T, E>::Residual` is not `E`, but `Result<Infallible, E>`.
152
    /// That way it's distinct from `ControlFlow<E>::Residual`, for example,
153
    /// and thus `?` on `ControlFlow` cannot be used in a method returning `Result`.
154
    ///
155
    /// If you're making a generic type `Foo<T>` that implements `Try<Output = T>`,
156
    /// then typically you can use `Foo<std::convert::Infallible>` as its `Residual`
157
    /// type: that type will have a "hole" in the correct place, and will maintain the
158
    /// "foo-ness" of the residual so other types need to opt-in to interconversion.
159
    #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
160
    type Residual;
161

            
162
    /// Constructs the type from its `Output` type.
163
    ///
164
    /// This should be implemented consistently with the `branch` method
165
    /// such that applying the `?` operator will get back the original value:
166
    /// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`.
167
    ///
168
    /// # Examples
169
    ///
170
    /// ```
171
    /// #![feature(try_trait_v2)]
172
    /// use std::ops::Try;
173
    ///
174
    /// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
175
    /// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
176
    /// assert_eq!(
177
    ///     <std::ops::ControlFlow<String, _> as Try>::from_output(5),
178
    ///     std::ops::ControlFlow::Continue(5),
179
    /// );
180
    ///
181
    /// # fn make_question_mark_work() -> Option<()> {
182
    /// assert_eq!(Option::from_output(4)?, 4);
183
    /// # None }
184
    /// # make_question_mark_work();
185
    ///
186
    /// // This is used, for example, on the accumulator in `try_fold`:
187
    /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
188
    /// assert_eq!(r, Some(4));
189
    /// ```
190
    #[lang = "from_output"]
191
    #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
192
    fn from_output(output: Self::Output) -> Self;
193

            
194
    /// Used in `?` to decide whether the operator should produce a value
195
    /// (because this returned [`ControlFlow::Continue`])
196
    /// or propagate a value back to the caller
197
    /// (because this returned [`ControlFlow::Break`]).
198
    ///
199
    /// # Examples
200
    ///
201
    /// ```
202
    /// #![feature(try_trait_v2)]
203
    /// use std::ops::{ControlFlow, Try};
204
    ///
205
    /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
206
    /// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
207
    ///
208
    /// assert_eq!(Some(3).branch(), ControlFlow::Continue(3));
209
    /// assert_eq!(None::<String>.branch(), ControlFlow::Break(None));
210
    ///
211
    /// assert_eq!(ControlFlow::<String, _>::Continue(3).branch(), ControlFlow::Continue(3));
212
    /// assert_eq!(
213
    ///     ControlFlow::<_, String>::Break(3).branch(),
214
    ///     ControlFlow::Break(ControlFlow::Break(3)),
215
    /// );
216
    /// ```
217
    #[lang = "branch"]
218
    #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
219
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
220
}
221

            
222
/// Used to specify which residuals can be converted into which [`crate::ops::Try`] types.
223
///
224
/// Every `Try` type needs to be recreatable from its own associated
225
/// `Residual` type, but can also have additional `FromResidual` implementations
226
/// to support interconversion with other `Try` types.
227
#[rustc_on_unimplemented(
228
    on(
229
        all(
230
            from_desugaring = "QuestionMark",
231
            Self = "core::result::Result<T, E>",
232
            R = "core::option::Option<core::convert::Infallible>",
233
        ),
234
        message = "the `?` operator can only be used on `Result`s, not `Option`s, \
235
            in {ItemContext} that returns `Result`",
236
        label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
237
        parent_label = "this function returns a `Result`"
238
    ),
239
    on(
240
        all(
241
            from_desugaring = "QuestionMark",
242
            Self = "core::result::Result<T, E>",
243
        ),
244
        // There's a special error message in the trait selection code for
245
        // `From` in `?`, so this is not shown for result-in-result errors,
246
        // and thus it can be phrased more strongly than `ControlFlow`'s.
247
        message = "the `?` operator can only be used on `Result`s \
248
            in {ItemContext} that returns `Result`",
249
        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
250
        parent_label = "this function returns a `Result`"
251
    ),
252
    on(
253
        all(
254
            from_desugaring = "QuestionMark",
255
            Self = "core::option::Option<T>",
256
            R = "core::result::Result<T, E>",
257
        ),
258
        message = "the `?` operator can only be used on `Option`s, not `Result`s, \
259
            in {ItemContext} that returns `Option`",
260
        label = "use `.ok()?` if you want to discard the `{R}` error information",
261
        parent_label = "this function returns an `Option`"
262
    ),
263
    on(
264
        all(
265
            from_desugaring = "QuestionMark",
266
            Self = "core::option::Option<T>",
267
        ),
268
        // `Option`-in-`Option` always works, as there's only one possible
269
        // residual, so this can also be phrased strongly.
270
        message = "the `?` operator can only be used on `Option`s \
271
            in {ItemContext} that returns `Option`",
272
        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
273
        parent_label = "this function returns an `Option`"
274
    ),
275
    on(
276
        all(
277
            from_desugaring = "QuestionMark",
278
            Self = "core::ops::control_flow::ControlFlow<B, C>",
279
            R = "core::ops::control_flow::ControlFlow<B, C>",
280
        ),
281
        message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
282
            can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
283
        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
284
        parent_label = "this function returns a `ControlFlow`",
285
        note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
286
    ),
287
    on(
288
        all(
289
            from_desugaring = "QuestionMark",
290
            Self = "core::ops::control_flow::ControlFlow<B, C>",
291
            // `R` is not a `ControlFlow`, as that case was matched previously
292
        ),
293
        message = "the `?` operator can only be used on `ControlFlow`s \
294
            in {ItemContext} that returns `ControlFlow`",
295
        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
296
        parent_label = "this function returns a `ControlFlow`",
297
    ),
298
    on(
299
        all(from_desugaring = "QuestionMark"),
300
        message = "the `?` operator can only be used in {ItemContext} \
301
                    that returns `Result` or `Option` \
302
                    (or another type that implements `{This}`)",
303
        label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
304
        parent_label = "this function should return `Result` or `Option` to accept `?`"
305
    ),
306
)]
307
#[rustc_diagnostic_item = "FromResidual"]
308
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
309
#[const_trait]
310
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
311
pub trait FromResidual<R = <Self as Try>::Residual> {
312
    /// Constructs the type from a compatible `Residual` type.
313
    ///
314
    /// This should be implemented consistently with the `branch` method such
315
    /// that applying the `?` operator will get back an equivalent residual:
316
    /// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`.
317
    /// (The residual is not mandated to be *identical* when interconversion is involved.)
318
    ///
319
    /// # Examples
320
    ///
321
    /// ```
322
    /// #![feature(try_trait_v2)]
323
    /// use std::ops::{ControlFlow, FromResidual};
324
    ///
325
    /// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
326
    /// assert_eq!(Option::<String>::from_residual(None), None);
327
    /// assert_eq!(
328
    ///     ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)),
329
    ///     ControlFlow::Break(5),
330
    /// );
331
    /// ```
332
    #[lang = "from_residual"]
333
    #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
334
    fn from_residual(residual: R) -> Self;
335
}
336

            
337
#[unstable(
338
    feature = "yeet_desugar_details",
339
    issue = "none",
340
    reason = "just here to simplify the desugaring; will never be stabilized"
341
)]
342
#[inline]
343
#[track_caller] // because `Result::from_residual` has it
344
#[lang = "from_yeet"]
345
#[allow(unreachable_pub)] // not-exposed but still used via lang-item
346
#[cfg(not(feature = "ferrocene_certified"))]
347
pub fn from_yeet<T, Y>(yeeted: Y) -> T
348
where
349
    T: FromResidual<Yeet<Y>>,
350
{
351
    FromResidual::from_residual(Yeet(yeeted))
352
}
353

            
354
/// Allows retrieving the canonical type implementing [`Try`] that has this type
355
/// as its residual and allows it to hold an `O` as its output.
356
///
357
/// If you think of the `Try` trait as splitting a type into its [`Try::Output`]
358
/// and [`Try::Residual`] components, this allows putting them back together.
359
///
360
/// For example,
361
/// `Result<T, E>: Try<Output = T, Residual = Result<Infallible, E>>`,
362
/// and in the other direction,
363
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
364
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
365
#[const_trait]
366
#[rustc_const_unstable(feature = "const_try", issue = "74935")]
367
pub trait Residual<O> {
368
    /// The "return" type of this meta-function.
369
    #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
370
    type TryType: Try<Output = O, Residual = Self>;
371
}
372

            
373
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
374
#[allow(type_alias_bounds)]
375
#[cfg(not(feature = "ferrocene_certified"))]
376
pub(crate) type ChangeOutputType<T: Try<Residual: Residual<V>>, V> =
377
    <T::Residual as Residual<V>>::TryType;
378

            
379
/// An adapter for implementing non-try methods via the `Try` implementation.
380
///
381
/// Conceptually the same as `Result<T, !>`, but requiring less work in trait
382
/// solving and inhabited-ness checking and such, by being an obvious newtype
383
/// and not having `From` bounds lying around.
384
///
385
/// Not currently planned to be exposed publicly, so just `pub(crate)`.
386
#[repr(transparent)]
387
#[cfg(not(feature = "ferrocene_certified"))]
388
pub(crate) struct NeverShortCircuit<T>(pub T);
389

            
390
#[cfg(not(feature = "ferrocene_certified"))]
391
impl<T> NeverShortCircuit<T> {
392
    /// Wraps a unary function to produce one that wraps the output into a `NeverShortCircuit`.
393
    ///
394
    /// This is useful for implementing infallible functions in terms of the `try_` ones,
395
    /// without accidentally capturing extra generic parameters in a closure.
396
    #[inline]
397
147
    pub(crate) fn wrap_mut_1<A>(
398
147
        mut f: impl FnMut(A) -> T,
399
147
    ) -> impl FnMut(A) -> NeverShortCircuit<T> {
400
11216
        move |a| NeverShortCircuit(f(a))
401
147
    }
402

            
403
    #[inline]
404
225
    pub(crate) fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
405
40351822
        move |a, b| NeverShortCircuit(f(a, b))
406
225
    }
407
}
408

            
409
#[cfg(not(feature = "ferrocene_certified"))]
410
pub(crate) enum NeverShortCircuitResidual {}
411

            
412
#[cfg(not(feature = "ferrocene_certified"))]
413
impl<T> Try for NeverShortCircuit<T> {
414
    type Output = T;
415
    type Residual = NeverShortCircuitResidual;
416

            
417
    #[inline]
418
45364001
    fn branch(self) -> ControlFlow<NeverShortCircuitResidual, T> {
419
45364001
        ControlFlow::Continue(self.0)
420
45364001
    }
421

            
422
    #[inline]
423
5001335
    fn from_output(x: T) -> Self {
424
5001335
        NeverShortCircuit(x)
425
5001335
    }
426
}
427

            
428
#[cfg(not(feature = "ferrocene_certified"))]
429
impl<T> FromResidual for NeverShortCircuit<T> {
430
    #[inline]
431
    fn from_residual(never: NeverShortCircuitResidual) -> Self {
432
        match never {}
433
    }
434
}
435

            
436
#[cfg(not(feature = "ferrocene_certified"))]
437
impl<T> Residual<T> for NeverShortCircuitResidual {
438
    type TryType = NeverShortCircuit<T>;
439
}
440

            
441
/// Implement `FromResidual<Yeet<T>>` on your type to enable
442
/// `do yeet expr` syntax in functions returning your type.
443
#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
444
#[derive(Debug)]
445
#[cfg(not(feature = "ferrocene_certified"))]
446
pub struct Yeet<T>(pub T);