Skip to content

Commit d059f26

Browse files
authored
Rollup merge of #76204 - NoraCodes:nora/control_flow_enum, r=scottmcm
Rename and expose LoopState as ControlFlow Basic PR for #75744. Addresses everything there except for documentation; lots of examples are probably a good idea.
2 parents a4e30a6 + 96eb5e1 commit d059f26

File tree

6 files changed

+119
-100
lines changed

6 files changed

+119
-100
lines changed

library/core/src/iter/adapters/mod.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::cmp;
22
use crate::fmt;
33
use crate::intrinsics;
4-
use crate::ops::{Add, AddAssign, Try};
4+
use crate::ops::{Add, AddAssign, ControlFlow, Try};
55

6-
use super::{from_fn, LoopState};
6+
use super::from_fn;
77
use super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen};
88

99
mod chain;
@@ -1164,10 +1164,10 @@ where
11641164
#[inline]
11651165
fn find<T, B>(
11661166
f: &mut impl FnMut(T) -> Option<B>,
1167-
) -> impl FnMut((), T) -> LoopState<(), B> + '_ {
1167+
) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ {
11681168
move |(), x| match f(x) {
1169-
Some(x) => LoopState::Break(x),
1170-
None => LoopState::Continue(()),
1169+
Some(x) => ControlFlow::Break(x),
1170+
None => ControlFlow::Continue(()),
11711171
}
11721172
}
11731173

@@ -1864,13 +1864,13 @@ where
18641864
flag: &'a mut bool,
18651865
p: &'a mut impl FnMut(&T) -> bool,
18661866
mut fold: impl FnMut(Acc, T) -> R + 'a,
1867-
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
1867+
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
18681868
move |acc, x| {
18691869
if p(&x) {
1870-
LoopState::from_try(fold(acc, x))
1870+
ControlFlow::from_try(fold(acc, x))
18711871
} else {
18721872
*flag = true;
1873-
LoopState::Break(Try::from_ok(acc))
1873+
ControlFlow::Break(Try::from_ok(acc))
18741874
}
18751875
}
18761876
}
@@ -1963,8 +1963,8 @@ where
19631963
{
19641964
let Self { iter, predicate } = self;
19651965
iter.try_fold(init, |acc, x| match predicate(x) {
1966-
Some(item) => LoopState::from_try(fold(acc, item)),
1967-
None => LoopState::Break(Try::from_ok(acc)),
1966+
Some(item) => ControlFlow::from_try(fold(acc, item)),
1967+
None => ControlFlow::Break(Try::from_ok(acc)),
19681968
})
19691969
.into_try()
19701970
}
@@ -2135,11 +2135,11 @@ where
21352135
fn check<T, Acc, R: Try<Ok = Acc>>(
21362136
mut n: usize,
21372137
mut fold: impl FnMut(Acc, T) -> R,
2138-
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> {
2138+
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> {
21392139
move |acc, x| {
21402140
n -= 1;
21412141
let r = fold(acc, x);
2142-
if n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) }
2142+
if n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
21432143
}
21442144
}
21452145

@@ -2246,11 +2246,11 @@ where
22462246
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
22472247
n: &'a mut usize,
22482248
mut fold: impl FnMut(Acc, T) -> R + 'a,
2249-
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
2249+
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
22502250
move |acc, x| {
22512251
*n -= 1;
22522252
let r = fold(acc, x);
2253-
if *n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) }
2253+
if *n == 0 { ControlFlow::Break(r) } else { ControlFlow::from_try(r) }
22542254
}
22552255
}
22562256

@@ -2414,10 +2414,10 @@ where
24142414
state: &'a mut St,
24152415
f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
24162416
mut fold: impl FnMut(Acc, B) -> R + 'a,
2417-
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
2417+
) -> impl FnMut(Acc, T) -> ControlFlow<Acc, R> + 'a {
24182418
move |acc, x| match f(state, x) {
2419-
None => LoopState::Break(Try::from_ok(acc)),
2420-
Some(x) => LoopState::from_try(fold(acc, x)),
2419+
None => ControlFlow::Break(Try::from_ok(acc)),
2420+
Some(x) => ControlFlow::from_try(fold(acc, x)),
24212421
}
24222422
}
24232423

@@ -2638,10 +2638,10 @@ where
26382638
let error = &mut *self.error;
26392639
self.iter
26402640
.try_fold(init, |acc, x| match x {
2641-
Ok(x) => LoopState::from_try(f(acc, x)),
2641+
Ok(x) => ControlFlow::from_try(f(acc, x)),
26422642
Err(e) => {
26432643
*error = Err(e);
2644-
LoopState::Break(Try::from_ok(acc))
2644+
ControlFlow::Break(Try::from_ok(acc))
26452645
}
26462646
})
26472647
.into_try()

library/core/src/iter/mod.rs

-56
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,6 @@
308308
309309
#![stable(feature = "rust1", since = "1.0.0")]
310310

311-
use crate::ops::Try;
312-
313311
#[stable(feature = "rust1", since = "1.0.0")]
314312
pub use self::traits::Iterator;
315313

@@ -367,57 +365,3 @@ mod adapters;
367365
mod range;
368366
mod sources;
369367
mod traits;
370-
371-
/// Used to make try_fold closures more like normal loops
372-
#[derive(PartialEq)]
373-
enum LoopState<C, B> {
374-
Continue(C),
375-
Break(B),
376-
}
377-
378-
impl<C, B> Try for LoopState<C, B> {
379-
type Ok = C;
380-
type Error = B;
381-
#[inline]
382-
fn into_result(self) -> Result<Self::Ok, Self::Error> {
383-
match self {
384-
LoopState::Continue(y) => Ok(y),
385-
LoopState::Break(x) => Err(x),
386-
}
387-
}
388-
#[inline]
389-
fn from_error(v: Self::Error) -> Self {
390-
LoopState::Break(v)
391-
}
392-
#[inline]
393-
fn from_ok(v: Self::Ok) -> Self {
394-
LoopState::Continue(v)
395-
}
396-
}
397-
398-
impl<C, B> LoopState<C, B> {
399-
#[inline]
400-
fn break_value(self) -> Option<B> {
401-
match self {
402-
LoopState::Continue(..) => None,
403-
LoopState::Break(x) => Some(x),
404-
}
405-
}
406-
}
407-
408-
impl<R: Try> LoopState<R::Ok, R> {
409-
#[inline]
410-
fn from_try(r: R) -> Self {
411-
match Try::into_result(r) {
412-
Ok(v) => LoopState::Continue(v),
413-
Err(v) => LoopState::Break(Try::from_error(v)),
414-
}
415-
}
416-
#[inline]
417-
fn into_try(self) -> R {
418-
match self {
419-
LoopState::Continue(v) => Try::from_ok(v),
420-
LoopState::Break(v) => v,
421-
}
422-
}
423-
}

library/core/src/iter/traits/double_ended.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use crate::iter::LoopState;
2-
use crate::ops::Try;
1+
use crate::ops::{ControlFlow, Try};
32

43
/// An iterator able to yield elements from both ends.
54
///
@@ -309,9 +308,9 @@ pub trait DoubleEndedIterator: Iterator {
309308
#[inline]
310309
fn check<T>(
311310
mut predicate: impl FnMut(&T) -> bool,
312-
) -> impl FnMut((), T) -> LoopState<(), T> {
311+
) -> impl FnMut((), T) -> ControlFlow<(), T> {
313312
move |(), x| {
314-
if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
313+
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
315314
}
316315
}
317316

library/core/src/iter/traits/iterator.rs

+26-21
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
// can't split that into multiple files.
44

55
use crate::cmp::{self, Ordering};
6-
use crate::ops::{Add, Try};
6+
use crate::ops::{Add, ControlFlow, Try};
77

8-
use super::super::LoopState;
98
use super::super::TrustedRandomAccess;
109
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
1110
use super::super::{FlatMap, Flatten};
@@ -2088,12 +2087,12 @@ pub trait Iterator {
20882087
F: FnMut(Self::Item) -> bool,
20892088
{
20902089
#[inline]
2091-
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> {
2090+
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
20922091
move |(), x| {
2093-
if f(x) { LoopState::Continue(()) } else { LoopState::Break(()) }
2092+
if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
20942093
}
20952094
}
2096-
self.try_fold((), check(f)) == LoopState::Continue(())
2095+
self.try_fold((), check(f)) == ControlFlow::Continue(())
20972096
}
20982097

20992098
/// Tests if any element of the iterator matches a predicate.
@@ -2141,13 +2140,13 @@ pub trait Iterator {
21412140
F: FnMut(Self::Item) -> bool,
21422141
{
21432142
#[inline]
2144-
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> LoopState<(), ()> {
2143+
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> {
21452144
move |(), x| {
2146-
if f(x) { LoopState::Break(()) } else { LoopState::Continue(()) }
2145+
if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
21472146
}
21482147
}
21492148

2150-
self.try_fold((), check(f)) == LoopState::Break(())
2149+
self.try_fold((), check(f)) == ControlFlow::Break(())
21512150
}
21522151

21532152
/// Searches for an element of an iterator that satisfies a predicate.
@@ -2203,9 +2202,9 @@ pub trait Iterator {
22032202
#[inline]
22042203
fn check<T>(
22052204
mut predicate: impl FnMut(&T) -> bool,
2206-
) -> impl FnMut((), T) -> LoopState<(), T> {
2205+
) -> impl FnMut((), T) -> ControlFlow<(), T> {
22072206
move |(), x| {
2208-
if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
2207+
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
22092208
}
22102209
}
22112210

@@ -2235,10 +2234,12 @@ pub trait Iterator {
22352234
F: FnMut(Self::Item) -> Option<B>,
22362235
{
22372236
#[inline]
2238-
fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> LoopState<(), B> {
2237+
fn check<T, B>(
2238+
mut f: impl FnMut(T) -> Option<B>,
2239+
) -> impl FnMut((), T) -> ControlFlow<(), B> {
22392240
move |(), x| match f(x) {
2240-
Some(x) => LoopState::Break(x),
2241-
None => LoopState::Continue(()),
2241+
Some(x) => ControlFlow::Break(x),
2242+
None => ControlFlow::Continue(()),
22422243
}
22432244
}
22442245

@@ -2274,15 +2275,15 @@ pub trait Iterator {
22742275
R: Try<Ok = bool>,
22752276
{
22762277
#[inline]
2277-
fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> LoopState<(), Result<T, R::Error>>
2278+
fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> ControlFlow<(), Result<T, R::Error>>
22782279
where
22792280
F: FnMut(&T) -> R,
22802281
R: Try<Ok = bool>,
22812282
{
22822283
move |(), x| match f(&x).into_result() {
2283-
Ok(false) => LoopState::Continue(()),
2284-
Ok(true) => LoopState::Break(Ok(x)),
2285-
Err(x) => LoopState::Break(Err(x)),
2284+
Ok(false) => ControlFlow::Continue(()),
2285+
Ok(true) => ControlFlow::Break(Ok(x)),
2286+
Err(x) => ControlFlow::Break(Err(x)),
22862287
}
22872288
}
22882289

@@ -2352,10 +2353,14 @@ pub trait Iterator {
23522353
#[inline]
23532354
fn check<T>(
23542355
mut predicate: impl FnMut(T) -> bool,
2355-
) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
2356+
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
23562357
// The addition might panic on overflow
23572358
move |i, x| {
2358-
if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(Add::add(i, 1)) }
2359+
if predicate(x) {
2360+
ControlFlow::Break(i)
2361+
} else {
2362+
ControlFlow::Continue(Add::add(i, 1))
2363+
}
23592364
}
23602365
}
23612366

@@ -2411,10 +2416,10 @@ pub trait Iterator {
24112416
#[inline]
24122417
fn check<T>(
24132418
mut predicate: impl FnMut(T) -> bool,
2414-
) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
2419+
) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> {
24152420
move |i, x| {
24162421
let i = i - 1;
2417-
if predicate(x) { LoopState::Break(i) } else { LoopState::Continue(i) }
2422+
if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i) }
24182423
}
24192424
}
24202425

library/core/src/ops/control_flow.rs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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+
}

library/core/src/ops/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140

141141
mod arith;
142142
mod bit;
143+
mod control_flow;
143144
mod deref;
144145
mod drop;
145146
mod function;
@@ -191,3 +192,6 @@ pub use self::unsize::CoerceUnsized;
191192

192193
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
193194
pub use self::unsize::DispatchFromDyn;
195+
196+
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
197+
pub use self::control_flow::ControlFlow;

0 commit comments

Comments
 (0)