Skip to content

Commit a834041

Browse files
committed
Remove finished flag from MapWhile
1 parent 266ecd6 commit a834041

File tree

2 files changed

+36
-47
lines changed

2 files changed

+36
-47
lines changed

src/libcore/iter/adapters/mod.rs

+21-47
Original file line numberDiff line numberDiff line change
@@ -1752,6 +1752,14 @@ where
17521752
}
17531753
}
17541754

1755+
#[stable(feature = "fused", since = "1.26.0")]
1756+
impl<I, P> FusedIterator for TakeWhile<I, P>
1757+
where
1758+
I: FusedIterator,
1759+
P: FnMut(&I::Item) -> bool,
1760+
{
1761+
}
1762+
17551763
/// An iterator that only accepts elements while `predicate` returns `Some(_)`.
17561764
///
17571765
/// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its
@@ -1764,20 +1772,19 @@ where
17641772
#[derive(Clone)]
17651773
pub struct MapWhile<I, P> {
17661774
iter: I,
1767-
finished: bool,
17681775
predicate: P,
17691776
}
17701777

17711778
impl<I, P> MapWhile<I, P> {
17721779
pub(super) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
1773-
MapWhile { iter, finished: false, predicate }
1780+
MapWhile { iter, predicate }
17741781
}
17751782
}
17761783

17771784
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
17781785
impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
17791786
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1780-
f.debug_struct("MapWhile").field("iter", &self.iter).field("flag", &self.finished).finish()
1787+
f.debug_struct("MapWhile").field("iter", &self.iter).finish()
17811788
}
17821789
}
17831790

@@ -1790,65 +1797,32 @@ where
17901797

17911798
#[inline]
17921799
fn next(&mut self) -> Option<B> {
1793-
if self.finished {
1794-
None
1795-
} else {
1796-
let x = self.iter.next()?;
1797-
let ret = (self.predicate)(x);
1798-
self.finished = ret.is_none();
1799-
ret
1800-
}
1800+
let x = self.iter.next()?;
1801+
(self.predicate)(x)
18011802
}
18021803

18031804
#[inline]
18041805
fn size_hint(&self) -> (usize, Option<usize>) {
1805-
if self.finished {
1806-
(0, Some(0))
1807-
} else {
1808-
let (_, upper) = self.iter.size_hint();
1809-
(0, upper) // can't know a lower bound, due to the predicate
1810-
}
1806+
let (_, upper) = self.iter.size_hint();
1807+
(0, upper) // can't know a lower bound, due to the predicate
18111808
}
18121809

18131810
#[inline]
1814-
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
1811+
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R
18151812
where
18161813
Self: Sized,
18171814
Fold: FnMut(Acc, Self::Item) -> R,
18181815
R: Try<Ok = Acc>,
18191816
{
1820-
fn check<'a, B, T, Acc, R: Try<Ok = Acc>>(
1821-
flag: &'a mut bool,
1822-
p: &'a mut impl FnMut(T) -> Option<B>,
1823-
mut fold: impl FnMut(Acc, B) -> R + 'a,
1824-
) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a {
1825-
move |acc, x| match p(x) {
1826-
Some(item) => LoopState::from_try(fold(acc, item)),
1827-
None => {
1828-
*flag = true;
1829-
LoopState::Break(Try::from_ok(acc))
1830-
}
1831-
}
1832-
}
1833-
1834-
if self.finished {
1835-
Try::from_ok(init)
1836-
} else {
1837-
let flag = &mut self.finished;
1838-
let p = &mut self.predicate;
1839-
self.iter.try_fold(init, check(flag, p, fold)).into_try()
1840-
}
1817+
let Self { iter, predicate } = self;
1818+
iter.try_fold(init, |acc, x| match predicate(x) {
1819+
Some(item) => LoopState::from_try(fold(acc, item)),
1820+
None => LoopState::Break(Try::from_ok(acc)),
1821+
})
1822+
.into_try()
18411823
}
18421824
}
18431825

1844-
#[stable(feature = "fused", since = "1.26.0")]
1845-
impl<I, P> FusedIterator for TakeWhile<I, P>
1846-
where
1847-
I: FusedIterator,
1848-
P: FnMut(&I::Item) -> bool,
1849-
{
1850-
}
1851-
18521826
/// An iterator that skips over `n` elements of `iter`.
18531827
///
18541828
/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its

src/libcore/iter/traits/iterator.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1114,8 +1114,23 @@ pub trait Iterator {
11141114
/// The `-3` is no longer there, because it was consumed in order to see if
11151115
/// the iteration should stop, but wasn't placed back into the iterator.
11161116
///
1117+
/// Note that unlike [`take_while`] this iterator is **not** fused:
1118+
///
1119+
/// ```
1120+
/// #![feature(iter_map_while)]
1121+
/// use std::convert::identity;
1122+
///
1123+
/// let mut iter = vec![Some(0), None, Some(1)].into_iter().map_while(identity);
1124+
/// assert_eq!(iter.next(), Some(0));
1125+
/// assert_eq!(iter.next(), None);
1126+
/// assert_eq!(iter.next(), Some(1));
1127+
/// ```
1128+
///
1129+
/// If you need fused iterator, use [`fuse`].
1130+
///
11171131
/// [`Some`]: ../../std/option/enum.Option.html#variant.Some
11181132
/// [`None`]: ../../std/option/enum.Option.html#variant.None
1133+
/// [`fuse`]: #method.fuse
11191134
#[inline]
11201135
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
11211136
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>

0 commit comments

Comments
 (0)