1use 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")]
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 `{Try}`)",
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 `{Try}`",
126 label = "the `?` operator cannot be applied to type `{Self}`"
127 )
128)]
129#[doc(alias = "?")]
130#[lang = "Try"]
131pub trait Try: FromResidual {
132 /// The type of the value produced by `?` when *not* short-circuiting.
133 #[unstable(feature = "try_trait_v2", issue = "84277")]
134 type Output;
135
136 /// The type of the value passed to [`FromResidual::from_residual`]
137 /// as part of `?` when short-circuiting.
138 ///
139 /// This represents the possible values of the `Self` type which are *not*
140 /// represented by the `Output` type.
141 ///
142 /// # Note to Implementors
143 ///
144 /// The choice of this type is critical to interconversion.
145 /// Unlike the `Output` type, which will often be a raw generic type,
146 /// this type is typically a newtype of some sort to "color" the type
147 /// so that it's distinguishable from the residuals of other types.
148 ///
149 /// This is why `Result<T, E>::Residual` is not `E`, but `Result<Infallible, E>`.
150 /// That way it's distinct from `ControlFlow<E>::Residual`, for example,
151 /// and thus `?` on `ControlFlow` cannot be used in a method returning `Result`.
152 ///
153 /// If you're making a generic type `Foo<T>` that implements `Try<Output = T>`,
154 /// then typically you can use `Foo<std::convert::Infallible>` as its `Residual`
155 /// type: that type will have a "hole" in the correct place, and will maintain the
156 /// "foo-ness" of the residual so other types need to opt-in to interconversion.
157 #[unstable(feature = "try_trait_v2", issue = "84277")]
158 type Residual;
159
160 /// Constructs the type from its `Output` type.
161 ///
162 /// This should be implemented consistently with the `branch` method
163 /// such that applying the `?` operator will get back the original value:
164 /// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`.
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// #![feature(try_trait_v2)]
170 /// use std::ops::Try;
171 ///
172 /// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
173 /// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
174 /// assert_eq!(
175 /// <std::ops::ControlFlow<String, _> as Try>::from_output(5),
176 /// std::ops::ControlFlow::Continue(5),
177 /// );
178 ///
179 /// # fn make_question_mark_work() -> Option<()> {
180 /// assert_eq!(Option::from_output(4)?, 4);
181 /// # None }
182 /// # make_question_mark_work();
183 ///
184 /// // This is used, for example, on the accumulator in `try_fold`:
185 /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
186 /// assert_eq!(r, Some(4));
187 /// ```
188 #[lang = "from_output"]
189 #[unstable(feature = "try_trait_v2", issue = "84277")]
190 fn from_output(output: Self::Output) -> Self;
191
192 /// Used in `?` to decide whether the operator should produce a value
193 /// (because this returned [`ControlFlow::Continue`])
194 /// or propagate a value back to the caller
195 /// (because this returned [`ControlFlow::Break`]).
196 ///
197 /// # Examples
198 ///
199 /// ```
200 /// #![feature(try_trait_v2)]
201 /// use std::ops::{ControlFlow, Try};
202 ///
203 /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
204 /// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
205 ///
206 /// assert_eq!(Some(3).branch(), ControlFlow::Continue(3));
207 /// assert_eq!(None::<String>.branch(), ControlFlow::Break(None));
208 ///
209 /// assert_eq!(ControlFlow::<String, _>::Continue(3).branch(), ControlFlow::Continue(3));
210 /// assert_eq!(
211 /// ControlFlow::<_, String>::Break(3).branch(),
212 /// ControlFlow::Break(ControlFlow::Break(3)),
213 /// );
214 /// ```
215 #[lang = "branch"]
216 #[unstable(feature = "try_trait_v2", issue = "84277")]
217 fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
218}
219
220/// Used to specify which residuals can be converted into which [`crate::ops::Try`] types.
221///
222/// Every `Try` type needs to be recreatable from its own associated
223/// `Residual` type, but can also have additional `FromResidual` implementations
224/// to support interconversion with other `Try` types.
225#[rustc_on_unimplemented(
226 on(
227 all(
228 from_desugaring = "QuestionMark",
229 _Self = "core::result::Result<T, E>",
230 R = "core::option::Option<core::convert::Infallible>",
231 ),
232 message = "the `?` operator can only be used on `Result`s, not `Option`s, \
233 in {ItemContext} that returns `Result`",
234 label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
235 parent_label = "this function returns a `Result`"
236 ),
237 on(
238 all(
239 from_desugaring = "QuestionMark",
240 _Self = "core::result::Result<T, E>",
241 ),
242 // There's a special error message in the trait selection code for
243 // `From` in `?`, so this is not shown for result-in-result errors,
244 // and thus it can be phrased more strongly than `ControlFlow`'s.
245 message = "the `?` operator can only be used on `Result`s \
246 in {ItemContext} that returns `Result`",
247 label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
248 parent_label = "this function returns a `Result`"
249 ),
250 on(
251 all(
252 from_desugaring = "QuestionMark",
253 _Self = "core::option::Option<T>",
254 R = "core::result::Result<T, E>",
255 ),
256 message = "the `?` operator can only be used on `Option`s, not `Result`s, \
257 in {ItemContext} that returns `Option`",
258 label = "use `.ok()?` if you want to discard the `{R}` error information",
259 parent_label = "this function returns an `Option`"
260 ),
261 on(
262 all(
263 from_desugaring = "QuestionMark",
264 _Self = "core::option::Option<T>",
265 ),
266 // `Option`-in-`Option` always works, as there's only one possible
267 // residual, so this can also be phrased strongly.
268 message = "the `?` operator can only be used on `Option`s \
269 in {ItemContext} that returns `Option`",
270 label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
271 parent_label = "this function returns an `Option`"
272 ),
273 on(
274 all(
275 from_desugaring = "QuestionMark",
276 _Self = "core::ops::control_flow::ControlFlow<B, C>",
277 R = "core::ops::control_flow::ControlFlow<B, C>",
278 ),
279 message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
280 can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
281 label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
282 parent_label = "this function returns a `ControlFlow`",
283 note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
284 ),
285 on(
286 all(
287 from_desugaring = "QuestionMark",
288 _Self = "core::ops::control_flow::ControlFlow<B, C>",
289 // `R` is not a `ControlFlow`, as that case was matched previously
290 ),
291 message = "the `?` operator can only be used on `ControlFlow`s \
292 in {ItemContext} that returns `ControlFlow`",
293 label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
294 parent_label = "this function returns a `ControlFlow`",
295 ),
296 on(
297 all(from_desugaring = "QuestionMark"),
298 message = "the `?` operator can only be used in {ItemContext} \
299 that returns `Result` or `Option` \
300 (or another type that implements `{FromResidual}`)",
301 label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
302 parent_label = "this function should return `Result` or `Option` to accept `?`"
303 ),
304)]
305#[rustc_diagnostic_item = "FromResidual"]
306#[unstable(feature = "try_trait_v2", issue = "84277")]
307pub trait FromResidual<R = <Self as Try>::Residual> {
308 /// Constructs the type from a compatible `Residual` type.
309 ///
310 /// This should be implemented consistently with the `branch` method such
311 /// that applying the `?` operator will get back an equivalent residual:
312 /// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`.
313 /// (The residual is not mandated to be *identical* when interconversion is involved.)
314 ///
315 /// # Examples
316 ///
317 /// ```
318 /// #![feature(try_trait_v2)]
319 /// use std::ops::{ControlFlow, FromResidual};
320 ///
321 /// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
322 /// assert_eq!(Option::<String>::from_residual(None), None);
323 /// assert_eq!(
324 /// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)),
325 /// ControlFlow::Break(5),
326 /// );
327 /// ```
328 #[lang = "from_residual"]
329 #[unstable(feature = "try_trait_v2", issue = "84277")]
330 fn from_residual(residual: R) -> Self;
331}
332
333#[unstable(
334 feature = "yeet_desugar_details",
335 issue = "none",
336 reason = "just here to simplify the desugaring; will never be stabilized"
337)]
338#[inline]
339#[track_caller] // because `Result::from_residual` has it
340#[lang = "from_yeet"]
341pub fn from_yeet<T, Y>(yeeted: Y) -> T
342where
343 T: FromResidual<Yeet<Y>>,
344{
345 FromResidual::from_residual(Yeet(yeeted))
346}
347
348/// Allows retrieving the canonical type implementing [`Try`] that has this type
349/// as its residual and allows it to hold an `O` as its output.
350///
351/// If you think of the `Try` trait as splitting a type into its [`Try::Output`]
352/// and [`Try::Residual`] components, this allows putting them back together.
353///
354/// For example,
355/// `Result<T, E>: Try<Output = T, Residual = Result<Infallible, E>>`,
356/// and in the other direction,
357/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
358#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
359pub trait Residual<O> {
360 /// The "return" type of this meta-function.
361 #[unstable(feature = "try_trait_v2_residual", issue = "91285")]
362 type TryType: Try<Output = O, Residual = Self>;
363}
364
365#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
366pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::TryType;
367
368/// An adapter for implementing non-try methods via the `Try` implementation.
369///
370/// Conceptually the same as `Result<T, !>`, but requiring less work in trait
371/// solving and inhabited-ness checking and such, by being an obvious newtype
372/// and not having `From` bounds lying around.
373///
374/// Not currently planned to be exposed publicly, so just `pub(crate)`.
375#[repr(transparent)]
376pub(crate) struct NeverShortCircuit<T>(pub T);
377
378impl<T> NeverShortCircuit<T> {
379 /// Wraps a unary function to produce one that wraps the output into a `NeverShortCircuit`.
380 ///
381 /// This is useful for implementing infallible functions in terms of the `try_` ones,
382 /// without accidentally capturing extra generic parameters in a closure.
383 #[inline]
384 pub fn wrap_mut_1<A>(mut f: impl FnMut(A) -> T) -> impl FnMut(A) -> NeverShortCircuit<T> {
385 move |a: A| NeverShortCircuit(f(a))
386 }
387
388 #[inline]
389 pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
390 move |a: A, b: B| NeverShortCircuit(f(a, b))
391 }
392}
393
394pub(crate) enum NeverShortCircuitResidual {}
395
396impl<T> Try for NeverShortCircuit<T> {
397 type Output = T;
398 type Residual = NeverShortCircuitResidual;
399
400 #[inline]
401 fn branch(self) -> ControlFlow<NeverShortCircuitResidual, T> {
402 ControlFlow::Continue(self.0)
403 }
404
405 #[inline]
406 fn from_output(x: T) -> Self {
407 NeverShortCircuit(x)
408 }
409}
410
411impl<T> FromResidual for NeverShortCircuit<T> {
412 #[inline]
413 fn from_residual(never: NeverShortCircuitResidual) -> Self {
414 match never {}
415 }
416}
417
418impl<T> Residual<T> for NeverShortCircuitResidual {
419 type TryType = NeverShortCircuit<T>;
420}
421
422/// Implement `FromResidual<Yeet<T>>` on your type to enable
423/// `do yeet expr` syntax in functions returning your type.
424#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
425#[derive(Debug)]
426pub struct Yeet<T>(pub T);
427