]> git.lizzy.rs Git - rust.git/blob - library/core/src/ops/control_flow.rs
Add 'compiler/rustc_codegen_cranelift/' from commit '793d26047f994e23415f8f6bb5686ff2...
[rust.git] / library / core / src / ops / control_flow.rs
1 use crate::ops::Try;
2
3 /// Used to make try_fold closures more like normal loops
4 #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
5 #[derive(Debug, Clone, Copy, PartialEq)]
6 pub enum ControlFlow<C, B> {
7     /// Continue in the loop, using the given value for the next iteration
8     Continue(C),
9     /// Exit the loop, yielding the given value
10     Break(B),
11 }
12
13 #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
14 impl<C, B> Try for ControlFlow<C, B> {
15     type Ok = C;
16     type Error = B;
17     #[inline]
18     fn into_result(self) -> Result<Self::Ok, Self::Error> {
19         match self {
20             ControlFlow::Continue(y) => Ok(y),
21             ControlFlow::Break(x) => Err(x),
22         }
23     }
24     #[inline]
25     fn from_error(v: Self::Error) -> Self {
26         ControlFlow::Break(v)
27     }
28     #[inline]
29     fn from_ok(v: Self::Ok) -> Self {
30         ControlFlow::Continue(v)
31     }
32 }
33
34 impl<C, B> ControlFlow<C, B> {
35     /// Converts the `ControlFlow` into an `Option` which is `Some` if the
36     /// `ControlFlow` was `Break` and `None` otherwise.
37     #[inline]
38     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
39     pub fn break_value(self) -> Option<B> {
40         match self {
41             ControlFlow::Continue(..) => None,
42             ControlFlow::Break(x) => Some(x),
43         }
44     }
45 }
46
47 impl<R: Try> ControlFlow<R::Ok, R> {
48     /// Create a `ControlFlow` from any type implementing `Try`.
49     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
50     #[inline]
51     pub fn from_try(r: R) -> Self {
52         match Try::into_result(r) {
53             Ok(v) => ControlFlow::Continue(v),
54             Err(v) => ControlFlow::Break(Try::from_error(v)),
55         }
56     }
57
58     /// Convert a `ControlFlow` into any type implementing `Try`;
59     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
60     #[inline]
61     pub fn into_try(self) -> R {
62         match self {
63             ControlFlow::Continue(v) => Try::from_ok(v),
64             ControlFlow::Break(v) => v,
65         }
66     }
67 }
68
69 impl<B> ControlFlow<(), B> {
70     /// It's frequently the case that there's no value needed with `Continue`,
71     /// so this provides a way to avoid typing `(())`, if you prefer it.
72     ///
73     /// # Examples
74     ///
75     /// ```
76     /// #![feature(control_flow_enum)]
77     /// use std::ops::ControlFlow;
78     ///
79     /// let mut partial_sum = 0;
80     /// let last_used = (1..10).chain(20..25).try_for_each(|x| {
81     ///     partial_sum += x;
82     ///     if partial_sum > 100 { ControlFlow::Break(x) }
83     ///     else { ControlFlow::CONTINUE }
84     /// });
85     /// assert_eq!(last_used.break_value(), Some(22));
86     /// ```
87     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
88     pub const CONTINUE: Self = ControlFlow::Continue(());
89 }
90
91 impl<C> ControlFlow<C, ()> {
92     /// APIs like `try_for_each` don't need values with `Break`,
93     /// so this provides a way to avoid typing `(())`, if you prefer it.
94     ///
95     /// # Examples
96     ///
97     /// ```
98     /// #![feature(control_flow_enum)]
99     /// use std::ops::ControlFlow;
100     ///
101     /// let mut partial_sum = 0;
102     /// (1..10).chain(20..25).try_for_each(|x| {
103     ///     if partial_sum > 100 { ControlFlow::BREAK }
104     ///     else { partial_sum += x; ControlFlow::CONTINUE }
105     /// });
106     /// assert_eq!(partial_sum, 108);
107     /// ```
108     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
109     pub const BREAK: Self = ControlFlow::Break(());
110 }