From d0af12560c9672546a6434e2e1e9ec72ad8f8e70 Mon Sep 17 00:00:00 2001 From: Leonora Tindall Date: Tue, 1 Sep 2020 11:44:32 -0500 Subject: [PATCH 1/2] Rename and expose LoopState as ControlFlow --- library/core/src/iter/adapters/mod.rs | 38 +++++------ library/core/src/iter/mod.rs | 55 ---------------- library/core/src/iter/traits/double_ended.rs | 7 +- library/core/src/iter/traits/iterator.rs | 41 ++++++------ library/core/src/ops/control_flow.rs | 67 ++++++++++++++++++++ library/core/src/ops/mod.rs | 4 ++ 6 files changed, 113 insertions(+), 99 deletions(-) create mode 100644 library/core/src/ops/control_flow.rs diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 9fcd137e1a634..e1ad8211a0309 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,9 +1,9 @@ use crate::cmp; use crate::fmt; use crate::intrinsics; -use crate::ops::{Add, AddAssign, Try}; +use crate::ops::{Add, AddAssign, Try, ControlFlow}; -use super::{from_fn, LoopState}; +use super::from_fn; use super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen}; mod chain; @@ -1164,10 +1164,10 @@ where #[inline] fn find( f: &mut impl FnMut(T) -> Option, - ) -> impl FnMut((), T) -> LoopState<(), B> + '_ { + ) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ { move |(), x| match f(x) { - Some(x) => LoopState::Break(x), - None => LoopState::Continue(()), + Some(x) => ControlFlow::Break(x), + None => ControlFlow::Continue(()), } } @@ -1864,13 +1864,13 @@ where flag: &'a mut bool, p: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, - ) -> impl FnMut(Acc, T) -> LoopState + 'a { + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { move |acc, x| { if p(&x) { - LoopState::from_try(fold(acc, x)) + ControlFlow::from_try(fold(acc, x)) } else { *flag = true; - LoopState::Break(Try::from_ok(acc)) + ControlFlow::Break(Try::from_ok(acc)) } } } @@ -1963,8 +1963,8 @@ where { let Self { iter, predicate } = self; iter.try_fold(init, |acc, x| match predicate(x) { - Some(item) => LoopState::from_try(fold(acc, item)), - None => LoopState::Break(Try::from_ok(acc)), + Some(item) => ControlFlow::from_try(fold(acc, item)), + None => ControlFlow::Break(Try::from_ok(acc)), }) .into_try() } @@ -2135,11 +2135,11 @@ where fn check>( mut n: usize, mut fold: impl FnMut(Acc, T) -> R, - ) -> impl FnMut(Acc, T) -> LoopState { + ) -> impl FnMut(Acc, T) -> ControlFlow { move |acc, x| { n -= 1; let r = fold(acc, x); - if n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } + if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) } } } @@ -2246,11 +2246,11 @@ where fn check<'a, T, Acc, R: Try>( n: &'a mut usize, mut fold: impl FnMut(Acc, T) -> R + 'a, - ) -> impl FnMut(Acc, T) -> LoopState + 'a { + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { move |acc, x| { *n -= 1; let r = fold(acc, x); - if *n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } + if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) } } } @@ -2414,10 +2414,10 @@ where state: &'a mut St, f: &'a mut impl FnMut(&mut St, T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, - ) -> impl FnMut(Acc, T) -> LoopState + 'a { + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { move |acc, x| match f(state, x) { - None => LoopState::Break(Try::from_ok(acc)), - Some(x) => LoopState::from_try(fold(acc, x)), + None => ControlFlow::Break(Try::from_ok(acc)), + Some(x) => ControlFlow::from_try(fold(acc, x)), } } @@ -2638,10 +2638,10 @@ where let error = &mut *self.error; self.iter .try_fold(init, |acc, x| match x { - Ok(x) => LoopState::from_try(f(acc, x)), + Ok(x) => ControlFlow::from_try(f(acc, x)), Err(e) => { *error = Err(e); - LoopState::Break(Try::from_ok(acc)) + ControlFlow::Break(Try::from_ok(acc)) } }) .into_try() diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 28b22f80e2c1b..51cb725a8e6b5 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -308,8 +308,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::ops::Try; - #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::Iterator; @@ -368,56 +366,3 @@ mod range; mod sources; mod traits; -/// Used to make try_fold closures more like normal loops -#[derive(PartialEq)] -enum LoopState { - Continue(C), - Break(B), -} - -impl Try for LoopState { - type Ok = C; - type Error = B; - #[inline] - fn into_result(self) -> Result { - match self { - LoopState::Continue(y) => Ok(y), - LoopState::Break(x) => Err(x), - } - } - #[inline] - fn from_error(v: Self::Error) -> Self { - LoopState::Break(v) - } - #[inline] - fn from_ok(v: Self::Ok) -> Self { - LoopState::Continue(v) - } -} - -impl LoopState { - #[inline] - fn break_value(self) -> Option { - match self { - LoopState::Continue(..) => None, - LoopState::Break(x) => Some(x), - } - } -} - -impl LoopState { - #[inline] - fn from_try(r: R) -> Self { - match Try::into_result(r) { - Ok(v) => LoopState::Continue(v), - Err(v) => LoopState::Break(Try::from_error(v)), - } - } - #[inline] - fn into_try(self) -> R { - match self { - LoopState::Continue(v) => Try::from_ok(v), - LoopState::Break(v) => v, - } - } -} diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 851a1e49a493b..3872fd4b6775b 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,5 +1,4 @@ -use crate::iter::LoopState; -use crate::ops::Try; +use crate::ops::{Try, ControlFlow}; /// An iterator able to yield elements from both ends. /// @@ -309,9 +308,9 @@ pub trait DoubleEndedIterator: Iterator { #[inline] fn check( mut predicate: impl FnMut(&T) -> bool, - ) -> impl FnMut((), T) -> LoopState<(), T> { + ) -> impl FnMut((), T) -> ControlFlow<(), T> { move |(), x| { - if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) } + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) } } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index aca6699b9efbb..31d9ff69e7f5f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3,9 +3,8 @@ // can't split that into multiple files. use crate::cmp::{self, Ordering}; -use crate::ops::{Add, Try}; +use crate::ops::{Add, Try, ControlFlow}; -use super::super::LoopState; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; use super::super::{FlatMap, Flatten}; @@ -2088,12 +2087,12 @@ pub trait Iterator { F: FnMut(Self::Item) -> bool, { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> { + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> { move |(), x| { - if f(x) { LoopState::Continue(()) } else { LoopState::Break(()) } + if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) } } } - self.try_fold((), check(f)) == LoopState::Continue(()) + self.try_fold((), check(f)) == ControlFlow::Continue(()) } /// Tests if any element of the iterator matches a predicate. @@ -2141,13 +2140,13 @@ pub trait Iterator { F: FnMut(Self::Item) -> bool, { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> { + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> { move |(), x| { - if f(x) { LoopState::Break(()) } else { LoopState::Continue(()) } + if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } } } - self.try_fold((), check(f)) == LoopState::Break(()) + self.try_fold((), check(f)) == ControlFlow::Break(()) } /// Searches for an element of an iterator that satisfies a predicate. @@ -2203,9 +2202,9 @@ pub trait Iterator { #[inline] fn check( mut predicate: impl FnMut(&T) -> bool, - ) -> impl FnMut((), T) -> LoopState<(), T> { + ) -> impl FnMut((), T) -> ControlFlow<(), T> { move |(), x| { - if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) } + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) } } } @@ -2235,10 +2234,10 @@ pub trait Iterator { F: FnMut(Self::Item) -> Option, { #[inline] - fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut((), T) -> LoopState<(), B> { + fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut((), T) -> ControlFlow<(), B> { move |(), x| match f(x) { - Some(x) => LoopState::Break(x), - None => LoopState::Continue(()), + Some(x) => ControlFlow::Break(x), + None => ControlFlow::Continue(()), } } @@ -2274,15 +2273,15 @@ pub trait Iterator { R: Try, { #[inline] - fn check(mut f: F) -> impl FnMut((), T) -> LoopState<(), Result> + fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow<(), Result> where F: FnMut(&T) -> R, R: Try, { move |(), x| match f(&x).into_result() { - Ok(false) => LoopState::Continue(()), - Ok(true) => LoopState::Break(Ok(x)), - Err(x) => LoopState::Break(Err(x)), + Ok(false) => ControlFlow::Continue(()), + Ok(true) => ControlFlow::Break(Ok(x)), + Err(x) => ControlFlow::Break(Err(x)), } } @@ -2352,10 +2351,10 @@ pub trait Iterator { #[inline] fn check( mut predicate: impl FnMut(T) -> bool, - ) -> impl FnMut(usize, T) -> LoopState { + ) -> impl FnMut(usize, T) -> ControlFlow { // The addition might panic on overflow move |i, x| { - if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(Add::add(i, 1)) } + if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(Add::add(i, 1)) } } } @@ -2411,10 +2410,10 @@ pub trait Iterator { #[inline] fn check( mut predicate: impl FnMut(T) -> bool, - ) -> impl FnMut(usize, T) -> LoopState { + ) -> impl FnMut(usize, T) -> ControlFlow { move |i, x| { let i = i - 1; - if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(i) } + if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i) } } } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs new file mode 100644 index 0000000000000..a0ed955768567 --- /dev/null +++ b/library/core/src/ops/control_flow.rs @@ -0,0 +1,67 @@ +use crate::ops::Try; + +/// Used to make try_fold closures more like normal loops +#[unstable(feature="control_flow_enum", reason="new API", issue="75744")] +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ControlFlow { + /// Continue in the loop, using the given value for the next iteration + Continue(C), + /// Exit the loop, yielding the given value + Break(B), +} + +#[unstable(feature="control_flow_enum", reason="new API", issue="75744")] +impl Try for ControlFlow { + type Ok = C; + type Error = B; + #[inline] + fn into_result(self) -> Result { + match self { + ControlFlow::Continue(y) => Ok(y), + ControlFlow::Break(x) => Err(x), + } + } + #[inline] + fn from_error(v: Self::Error) -> Self { + ControlFlow::Break(v) + } + #[inline] + fn from_ok(v: Self::Ok) -> Self { + ControlFlow::Continue(v) + } +} + +impl ControlFlow { + /// Converts the `ControlFlow` into an `Option` which is `Some` if the + /// `ControlFlow` was `Break` and `None` otherwise. + #[inline] + #[unstable(feature="control_flow_enum", reason="new API", issue="75744")] + pub fn break_value(self) -> Option { + match self { + ControlFlow::Continue(..) => None, + ControlFlow::Break(x) => Some(x), + } + } +} + +impl ControlFlow { + /// Create a `ControlFlow` from any type implementing `Try`. + #[unstable(feature="control_flow_enum", reason="new API", issue="75744")] + #[inline] + pub fn from_try(r: R) -> Self { + match Try::into_result(r) { + Ok(v) => ControlFlow::Continue(v), + Err(v) => ControlFlow::Break(Try::from_error(v)), + } + } + + /// Convert a `ControlFlow` into any type implementing `Try`; + #[unstable(feature="control_flow_enum", reason="new API", issue="75744")] + #[inline] + pub fn into_try(self) -> R { + match self { + ControlFlow::Continue(v) => Try::from_ok(v), + ControlFlow::Break(v) => v, + } + } +} diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index c19bd6e441e69..befc644054fb2 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -148,6 +148,7 @@ mod index; mod range; mod r#try; mod unsize; +mod control_flow; #[stable(feature = "rust1", since = "1.0.0")] pub use self::arith::{Add, Div, Mul, Neg, Rem, Sub}; @@ -191,3 +192,6 @@ pub use self::unsize::CoerceUnsized; #[unstable(feature = "dispatch_from_dyn", issue = "none")] pub use self::unsize::DispatchFromDyn; + +#[unstable(feature="control_flow_enum", reason="new API", issue="75744")] +pub use self::control_flow::ControlFlow; From 96eb5e175190c7d0020b36c2856bbcf160dad793 Mon Sep 17 00:00:00 2001 From: Leonora Tindall Date: Wed, 2 Sep 2020 14:12:21 -0500 Subject: [PATCH 2/2] Format ControlFlow changes with rustfmt --- library/core/src/iter/adapters/mod.rs | 2 +- library/core/src/iter/mod.rs | 1 - library/core/src/iter/traits/double_ended.rs | 2 +- library/core/src/iter/traits/iterator.rs | 12 +++++++++--- library/core/src/ops/control_flow.rs | 10 +++++----- library/core/src/ops/mod.rs | 4 ++-- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index e1ad8211a0309..f32c3963abea2 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,7 +1,7 @@ use crate::cmp; use crate::fmt; use crate::intrinsics; -use crate::ops::{Add, AddAssign, Try, ControlFlow}; +use crate::ops::{Add, AddAssign, ControlFlow, Try}; use super::from_fn; use super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen}; diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 51cb725a8e6b5..fac6693aff079 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -365,4 +365,3 @@ mod adapters; mod range; mod sources; mod traits; - diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 3872fd4b6775b..25230519f3744 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,4 +1,4 @@ -use crate::ops::{Try, ControlFlow}; +use crate::ops::{ControlFlow, Try}; /// An iterator able to yield elements from both ends. /// diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 31d9ff69e7f5f..657d04a4d6288 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3,7 +3,7 @@ // can't split that into multiple files. use crate::cmp::{self, Ordering}; -use crate::ops::{Add, Try, ControlFlow}; +use crate::ops::{Add, ControlFlow, Try}; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; @@ -2234,7 +2234,9 @@ pub trait Iterator { F: FnMut(Self::Item) -> Option, { #[inline] - fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut((), T) -> ControlFlow<(), B> { + fn check( + mut f: impl FnMut(T) -> Option, + ) -> impl FnMut((), T) -> ControlFlow<(), B> { move |(), x| match f(x) { Some(x) => ControlFlow::Break(x), None => ControlFlow::Continue(()), @@ -2354,7 +2356,11 @@ pub trait Iterator { ) -> impl FnMut(usize, T) -> ControlFlow { // The addition might panic on overflow move |i, x| { - if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(Add::add(i, 1)) } + if predicate(x) { + ControlFlow::Break(i) + } else { + ControlFlow::Continue(Add::add(i, 1)) + } } } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index a0ed955768567..687d423dcb635 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -1,7 +1,7 @@ use crate::ops::Try; /// Used to make try_fold closures more like normal loops -#[unstable(feature="control_flow_enum", reason="new API", issue="75744")] +#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow { /// Continue in the loop, using the given value for the next iteration @@ -10,7 +10,7 @@ pub enum ControlFlow { Break(B), } -#[unstable(feature="control_flow_enum", reason="new API", issue="75744")] +#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] impl Try for ControlFlow { type Ok = C; type Error = B; @@ -35,7 +35,7 @@ impl ControlFlow { /// Converts the `ControlFlow` into an `Option` which is `Some` if the /// `ControlFlow` was `Break` and `None` otherwise. #[inline] - #[unstable(feature="control_flow_enum", reason="new API", issue="75744")] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] pub fn break_value(self) -> Option { match self { ControlFlow::Continue(..) => None, @@ -46,7 +46,7 @@ impl ControlFlow { impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. - #[unstable(feature="control_flow_enum", reason="new API", issue="75744")] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[inline] pub fn from_try(r: R) -> Self { match Try::into_result(r) { @@ -56,7 +56,7 @@ impl ControlFlow { } /// Convert a `ControlFlow` into any type implementing `Try`; - #[unstable(feature="control_flow_enum", reason="new API", issue="75744")] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[inline] pub fn into_try(self) -> R { match self { diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index befc644054fb2..2a4186f9d5db9 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -140,6 +140,7 @@ mod arith; mod bit; +mod control_flow; mod deref; mod drop; mod function; @@ -148,7 +149,6 @@ mod index; mod range; mod r#try; mod unsize; -mod control_flow; #[stable(feature = "rust1", since = "1.0.0")] pub use self::arith::{Add, Div, Mul, Neg, Rem, Sub}; @@ -193,5 +193,5 @@ pub use self::unsize::CoerceUnsized; #[unstable(feature = "dispatch_from_dyn", issue = "none")] pub use self::unsize::DispatchFromDyn; -#[unstable(feature="control_flow_enum", reason="new API", issue="75744")] +#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] pub use self::control_flow::ControlFlow;