radicle_std_ext/
ops.rs

1//! Provides Try-trait for stable rust
2//!
3//! Probably doesn't work with `?`-desugaring. If the `nightly` feature is
4//! enabled for this crate, the `std` version is enabled.
5
6#[cfg(not(feature = "nightly"))]
7pub use stable::{FromResidual, Try};
8#[cfg(feature = "nightly")]
9pub use std::ops::{FromResidual, Try};
10
11mod stable {
12    use std::{convert, ops::ControlFlow, task::Poll};
13
14    pub trait Try: FromResidual {
15        type Output;
16        type Residual;
17
18        fn from_output(output: Self::Output) -> Self;
19        fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
20    }
21
22    pub trait FromResidual<R = <Self as Try>::Residual> {
23        fn from_residual(residual: R) -> Self;
24    }
25
26    impl<B, C> Try for ControlFlow<B, C> {
27        type Output = C;
28        type Residual = ControlFlow<B, convert::Infallible>;
29
30        #[inline]
31        fn from_output(output: Self::Output) -> Self {
32            ControlFlow::Continue(output)
33        }
34
35        #[inline]
36        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
37            match self {
38                ControlFlow::Continue(c) => ControlFlow::Continue(c),
39                ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
40            }
41        }
42    }
43
44    impl<B, C> FromResidual for ControlFlow<B, C> {
45        #[inline]
46        fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
47            match residual {
48                ControlFlow::Break(b) => ControlFlow::Break(b),
49                _ => unreachable!(),
50            }
51        }
52    }
53
54    impl<T> Try for Option<T> {
55        type Output = T;
56        type Residual = Option<convert::Infallible>;
57
58        #[inline]
59        fn from_output(output: Self::Output) -> Self {
60            Some(output)
61        }
62
63        #[inline]
64        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
65            match self {
66                Some(v) => ControlFlow::Continue(v),
67                None => ControlFlow::Break(None),
68            }
69        }
70    }
71
72    impl<T> FromResidual for Option<T> {
73        #[inline]
74        fn from_residual(residual: Option<convert::Infallible>) -> Self {
75            match residual {
76                None => None,
77                _ => unreachable!(),
78            }
79        }
80    }
81
82    impl<T, E> Try for Result<T, E> {
83        type Output = T;
84        type Residual = Result<convert::Infallible, E>;
85
86        #[inline]
87        fn from_output(output: Self::Output) -> Self {
88            Ok(output)
89        }
90
91        #[inline]
92        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
93            match self {
94                Ok(v) => ControlFlow::Continue(v),
95                Err(e) => ControlFlow::Break(Err(e)),
96            }
97        }
98    }
99
100    impl<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Result<T, F> {
101        #[inline]
102        fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
103            match residual {
104                Err(e) => Err(From::from(e)),
105                _ => unreachable!(),
106            }
107        }
108    }
109
110    impl<T, E> Try for Poll<Option<Result<T, E>>> {
111        type Output = Poll<Option<T>>;
112        type Residual = Result<convert::Infallible, E>;
113
114        #[inline]
115        fn from_output(c: Self::Output) -> Self {
116            c.map(|x| x.map(Ok))
117        }
118
119        #[inline]
120        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
121            match self {
122                Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
123                Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
124                Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
125                Poll::Pending => ControlFlow::Continue(Poll::Pending),
126            }
127        }
128    }
129
130    impl<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Poll<Option<Result<T, F>>> {
131        #[inline]
132        fn from_residual(x: Result<convert::Infallible, E>) -> Self {
133            match x {
134                Err(e) => Poll::Ready(Some(Err(From::from(e)))),
135                _ => unreachable!(),
136            }
137        }
138    }
139
140    impl<T, E> Try for Poll<Result<T, E>> {
141        type Output = Poll<T>;
142        type Residual = Result<convert::Infallible, E>;
143
144        #[inline]
145        fn from_output(c: Self::Output) -> Self {
146            c.map(Ok)
147        }
148
149        #[inline]
150        fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
151            match self {
152                Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
153                Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
154                Poll::Pending => ControlFlow::Continue(Poll::Pending),
155            }
156        }
157    }
158
159    impl<T, E, F: From<E>> FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
160        #[inline]
161        fn from_residual(x: Result<convert::Infallible, E>) -> Self {
162            match x {
163                Err(e) => Poll::Ready(Err(From::from(e))),
164                _ => unreachable!(),
165            }
166        }
167    }
168}