diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 6c597301ac204..b0aca65834370 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -282,6 +282,12 @@ bench_sums! { (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111) } +bench_sums! { + bench_cycle_take_sum, + bench_cycle_take_ref_sum, + (0i64..10000).cycle().take(1000000) +} + // Checks whether Skip> is as fast as Zip, Skip>, from // https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743 #[bench] diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index de7ab8843daed..7b273f7862a1f 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -649,6 +649,19 @@ impl Iterator for Cycle where I: Clone + Iterator { _ => (usize::MAX, None) } } + + #[inline] + fn try_fold(&mut self, init: Acc, mut f: F) -> R where + Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try + { + let mut accum = init; + while let Some(x) = self.iter.next() { + accum = f(accum, x)?; + accum = self.iter.try_fold(accum, &mut f)?; + self.iter = self.orig.clone(); + } + Try::from_ok(accum) + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1855,18 +1868,11 @@ impl Iterator for Peekable { #[inline] fn nth(&mut self, n: usize) -> Option { - // FIXME(#43234): merge these when borrow-checking gets better. - if n == 0 { - match self.peeked.take() { - Some(v) => v, - None => self.iter.nth(n), - } - } else { - match self.peeked.take() { - Some(None) => None, - Some(Some(_)) => self.iter.nth(n - 1), - None => self.iter.nth(n), - } + match self.peeked.take() { + Some(None) => None, + Some(v @ Some(_)) if n == 0 => v, + Some(Some(_)) => self.iter.nth(n - 1), + None => self.iter.nth(n), } } @@ -1965,14 +1971,8 @@ impl Peekable { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&mut self) -> Option<&I::Item> { - if self.peeked.is_none() { - self.peeked = Some(self.iter.next()); - } - match self.peeked { - Some(Some(ref value)) => Some(value), - Some(None) => None, - _ => unreachable!(), - } + let iter = &mut self.iter; + self.peeked.get_or_insert_with(|| iter.next()).as_ref() } } @@ -2109,8 +2109,12 @@ impl Iterator for TakeWhile #[inline] fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate + if self.flag { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } } #[inline] @@ -2321,6 +2325,10 @@ impl Iterator for Take where I: Iterator{ #[inline] fn size_hint(&self) -> (usize, Option) { + if self.n == 0 { + return (0, Some(0)); + } + let (lower, upper) = self.iter.size_hint(); let lower = cmp::min(lower, self.n); diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 726e891df0ccf..1287e11cff47b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -92,6 +92,7 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] +#![feature(bind_by_move_pattern_guards)] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 19be1a07c5baa..4efa01363146b 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1001,6 +1001,8 @@ fn test_cycle() { let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); + + assert_eq!(empty::().cycle().fold(0, |acc, x| acc + x), 0); } #[test]