diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 3c0ddcb2bc871..6759a6b2d7349 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1768,6 +1768,14 @@ where } } +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for TakeWhile +where + I: FusedIterator, + P: FnMut(&I::Item) -> bool, +{ +} + /// An iterator that only accepts elements while `predicate` returns `Some(_)`. /// /// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its @@ -1780,20 +1788,19 @@ where #[derive(Clone)] pub struct MapWhile { iter: I, - finished: bool, predicate: P, } impl MapWhile { pub(super) fn new(iter: I, predicate: P) -> MapWhile { - MapWhile { iter, finished: false, predicate } + MapWhile { iter, predicate } } } #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] impl fmt::Debug for MapWhile { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MapWhile").field("iter", &self.iter).field("flag", &self.finished).finish() + f.debug_struct("MapWhile").field("iter", &self.iter).finish() } } @@ -1806,65 +1813,32 @@ where #[inline] fn next(&mut self) -> Option { - if self.finished { - None - } else { - let x = self.iter.next()?; - let ret = (self.predicate)(x); - self.finished = ret.is_none(); - ret - } + let x = self.iter.next()?; + (self.predicate)(x) } #[inline] fn size_hint(&self) -> (usize, Option) { - if self.finished { - (0, Some(0)) - } else { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate - } + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate } #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R + fn try_fold(&mut self, init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - fn check<'a, B, T, Acc, R: Try>( - flag: &'a mut bool, - p: &'a mut impl FnMut(T) -> Option, - mut fold: impl FnMut(Acc, B) -> R + 'a, - ) -> impl FnMut(Acc, T) -> LoopState + 'a { - move |acc, x| match p(x) { - Some(item) => LoopState::from_try(fold(acc, item)), - None => { - *flag = true; - LoopState::Break(Try::from_ok(acc)) - } - } - } - - if self.finished { - Try::from_ok(init) - } else { - let flag = &mut self.finished; - let p = &mut self.predicate; - self.iter.try_fold(init, check(flag, p, fold)).into_try() - } + 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)), + }) + .into_try() } } -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for TakeWhile -where - I: FusedIterator, - P: FnMut(&I::Item) -> bool, -{ -} - /// An iterator that skips over `n` elements of `iter`. /// /// This `struct` is created by the [`skip`] method on [`Iterator`]. See its diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index e2ebef9c6ce2f..39bd270da8680 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1037,9 +1037,6 @@ pub trait Iterator { /// closure on each element of the iterator, and yield elements /// while it returns [`Some(_)`][`Some`]. /// - /// After [`None`] is returned, `map_while()`'s job is over, and the - /// rest of the elements are ignored. - /// /// # Examples /// /// Basic usage: @@ -1079,15 +1076,14 @@ pub trait Iterator { /// #![feature(iter_map_while)] /// use std::convert::TryFrom; /// - /// let a = [0, -1, 1, -2]; - /// - /// let mut iter = a.iter().map_while(|x| u32::try_from(*x).ok()); + /// let a = [0, 1, 2, -3, 4, 5, -6]; /// - /// assert_eq!(iter.next(), Some(0u32)); + /// let iter = a.iter().map_while(|x| u32::try_from(*x).ok()); + /// let vec = iter.collect::>(); /// - /// // We have more elements that are fit in u32, but since we already - /// // got a None, map_while() isn't used any more - /// assert_eq!(iter.next(), None); + /// // We have more elements which could fit in u32 (4, 5), but `map_while` returned `None` for `-3` + /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` entcountered. + /// assert_eq!(vec, vec![0, 1, 2]); /// ``` /// /// Because `map_while()` needs to look at the value in order to see if it @@ -1115,8 +1111,13 @@ pub trait Iterator { /// The `-3` is no longer there, because it was consumed in order to see if /// the iteration should stop, but wasn't placed back into the iterator. /// + /// Note that unlike [`take_while`] this iterator is **not** fused. + /// It is also not specified what this iterator returns after the first` None` is returned. + /// If you need fused iterator, use [`fuse`]. + /// /// [`Some`]: ../../std/option/enum.Option.html#variant.Some /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`fuse`]: #method.fuse #[inline] #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] fn map_while(self, predicate: P) -> MapWhile