heap_array/
try_me.rs

1use core::convert::Infallible;
2use core::ops::ControlFlow;
3
4type Residual<T> = <T as Try>::TryType<Infallible>;
5
6mod sealed {
7    use super::NeverShortCircuit;
8    pub trait Sealed {}
9
10    impl<T> Sealed for Option<T> {}
11    impl<T, E> Sealed for Result<T, E> {}
12    impl<T> Sealed for NeverShortCircuit<T> {}
13}
14
15pub trait Try: sealed::Sealed {
16    type Output;
17    type TryType<T>;
18
19    fn from_element<ELM>(e: ELM) -> Self::TryType<ELM>;
20    fn from_residual<T>(residual: Residual<Self>) -> Self::TryType<T>;
21    fn branch(self) -> ControlFlow<Residual<Self>, Self::Output>;
22}
23
24
25macro_rules! try_impl {
26    (
27        $T: ident < T $(, $($generics: tt),* )? >,
28        $success:ident ($output:ident),
29        $fail: ident $(($err:ident))?
30    ) => {
31        impl<T $(, $($generics)*)?> Try for $T<T $(, $($generics)*)?> {
32            type Output = T;
33            type TryType<TT> = $T<TT $(, $($generics)* )?>;
34
35            #[inline(always)]
36            fn from_element<ELM>(e: ELM) -> Self::TryType<ELM> {
37                $success(e)
38            }
39
40            #[inline(always)]
41            fn from_residual<TT>(residual: Residual<Self>) -> Self::TryType<TT> {
42                match residual {
43                    $success(infallible) => match infallible {},
44                    $fail$(($err))? => {$fail$(($err))?}
45                }
46            }
47
48            #[inline(always)]
49            fn branch(self) -> ControlFlow<Residual<Self>, Self::Output> {
50                match self {
51                    $success($output) => ControlFlow::Continue($output),
52                    $fail$(($err))? => ControlFlow::Break($fail$(($err))?)
53                }
54            }
55        }
56    };
57}
58
59try_impl! {
60    Option<T>, Some(out), None
61}
62try_impl! {
63    Result<T, E>, Ok(out), Err(err)
64}
65
66
67pub(crate) struct NeverShortCircuit<T>(pub T);
68
69impl<T> NeverShortCircuit<T> {
70    #[inline(always)]
71    pub fn wrap_fn<Arg>(mut f: impl FnMut(Arg) -> T) -> impl FnMut(Arg) -> NeverShortCircuit<T> {
72        move |arg| NeverShortCircuit(f(arg))
73    }
74}
75
76impl<T> Try for NeverShortCircuit<T> {
77    type Output = T;
78    type TryType<TT> = TT;
79
80    #[inline(always)]
81    fn from_element<ELM>(e: ELM) -> Self::TryType<ELM> { e }
82
83    #[inline(always)]
84    fn from_residual<TT>(infallible: Residual<Self>) -> Self::TryType<TT> {
85        match infallible {}
86    }
87
88    #[inline(always)]
89    fn branch(self) -> ControlFlow<Residual<Self>, Self::Output> {
90        ControlFlow::Continue(self.0)
91    }
92}