about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-12-09 00:18:34 +0000
committerbors <bors@rust-lang.org>2018-12-09 00:18:34 +0000
commitb7da2c6e12a6b2a2343e2f1e66fe4f6a1ad55463 (patch)
tree481ef614252d8aa77850a9517772b20b1ea09d93 /src
parentd7a9d961c349bb7826ece463e51f10667a9fb851 (diff)
parent5728a043e8280e96cbae784a731d43f2c7a50137 (diff)
downloadrust-b7da2c6e12a6b2a2343e2f1e66fe4f6a1ad55463.tar.gz
rust-b7da2c6e12a6b2a2343e2f1e66fe4f6a1ad55463.zip
Auto merge of #56630 - sinkuu:core_iter, r=kennytm
Resolve FIXME in libcore/iter/mod.rs

and makes a few improvements.
Diffstat (limited to 'src')
-rw-r--r--src/libcore/benches/iter.rs6
-rw-r--r--src/libcore/iter/mod.rs52
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/tests/iter.rs2
4 files changed, 39 insertions, 22 deletions
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index 6c597301ac2..b0aca658343 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<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, 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 de7ab8843da..7b273f7862a 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -649,6 +649,19 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
             _ => (usize::MAX, None)
         }
     }
+
+    #[inline]
+    fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
+        Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+    {
+        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<I: Iterator> Iterator for Peekable<I> {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
-        // 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<I: Iterator> Peekable<I> {
     #[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<I: Iterator, P> Iterator for TakeWhile<I, P>
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        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<I> Iterator for Take<I> where I: Iterator{
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
+        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 726e891df0c..1287e11cff4 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 19be1a07c5b..4efa0136314 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::<i32>().cycle().fold(0, |acc, x| acc + x), 0);
 }
 
 #[test]