diff options
| author | bors <bors@rust-lang.org> | 2020-03-22 11:57:58 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-03-22 11:57:58 +0000 |
| commit | 5ae85f43f4eeaf177cd12f47958b7ff62786b612 (patch) | |
| tree | 6e91c9881063d776b52e05bada95e8acb4139db3 /src/libcore | |
| parent | 94d43d656665e59abc10c7c22a3194685e7cc605 (diff) | |
| parent | e964d7180ca4164dfa3d6c6dee6026889c604812 (diff) | |
| download | rust-5ae85f43f4eeaf177cd12f47958b7ff62786b612.tar.gz rust-5ae85f43f4eeaf177cd12f47958b7ff62786b612.zip | |
Auto merge of #68820 - WaffleLapkin:remove_finished_from_map_while, r=LukasKalbertodt
Remove `finished` flag from `MapWhile` This PR removes `finished` flag from `MapWhile` as been proposed in https://github.com/rust-lang/rust/pull/66577#discussion_r370958025. This also resolves open questions of the tracking issue (#68537): - `MapWhile` can't implement both + `DoubleEndedIterator` (discussed in https://github.com/rust-lang/rust/pull/66577#discussion_r370947990 and following comments) + `FusedIterator` (this pr removes `finished` flag, so `MapWhile` isn't fused anymore) - Debug output (this pr removes `finished` flag, so there is no question in including it in debug output) r? @Mark-Simulacrum
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/iter/adapters/mod.rs | 68 | ||||
| -rw-r--r-- | src/libcore/iter/traits/iterator.rs | 21 |
2 files changed, 32 insertions, 57 deletions
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 3c0ddcb2bc8..6759a6b2d73 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<I, P> FusedIterator for TakeWhile<I, P> +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<I, P> { iter: I, - finished: bool, predicate: P, } impl<I, P> MapWhile<I, P> { pub(super) fn new(iter: I, predicate: P) -> MapWhile<I, P> { - MapWhile { iter, finished: false, predicate } + MapWhile { iter, predicate } } } #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> { 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<B> { - 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<usize>) { - 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<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok = Acc>, { - fn check<'a, B, T, Acc, R: Try<Ok = Acc>>( - flag: &'a mut bool, - p: &'a mut impl FnMut(T) -> Option<B>, - mut fold: impl FnMut(Acc, B) -> R + 'a, - ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + '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<I, P> FusedIterator for TakeWhile<I, P> -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 e2ebef9c6ce..39bd270da86 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::<Vec<_>>(); /// - /// // 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<B, P>(self, predicate: P) -> MapWhile<Self, P> |
