about summary refs log tree commit diff
diff options
context:
space:
mode:
authorroot <root@localhost>2014-08-24 15:04:28 +0200
committerroot <root@localhost>2014-08-24 15:11:23 +0200
commitd363770851650d9e137d628de2efeb90b3154bb0 (patch)
tree5c3b7863d8a28124475bfa0a486cd6567431e7a1
parent262d5a4686c80675fe5bfcb79b26b341b9a0bf7a (diff)
downloadrust-d363770851650d9e137d628de2efeb90b3154bb0.tar.gz
rust-d363770851650d9e137d628de2efeb90b3154bb0.zip
libcore: Simplify Enumerate, Zip::next_back
Use ExactSize::len() and defer to its decisions about overly defensive
assertions. Remove the length double-check and simply put a failure
case if the Zip finds an uneven end in .next_back().

Fixing this up since I think I wrote this, and it's been known to
confuse rusties (PR#15886).
-rw-r--r--src/libcore/iter.rs34
1 files changed, 18 insertions, 16 deletions
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index b8ed8bdf923..b2bd8d46fb5 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -728,6 +728,10 @@ pub trait ExactSize<A> : DoubleEndedIterator<A> {
     /// Return the exact length of the iterator.
     fn len(&self) -> uint {
         let (lower, upper) = self.size_hint();
+        // Note: This assertion is overly defensive, but it checks the invariant
+        // guaranteed by the trait. If this trait were rust-internal,
+        // we could use debug_assert!; assert_eq! will check all Rust user
+        // implementations too.
         assert_eq!(upper, Some(lower));
         lower
     }
@@ -1195,21 +1199,20 @@ impl<A, B, T: ExactSize<A>, U: ExactSize<B>> DoubleEndedIterator<(A, B)>
 for Zip<T, U> {
     #[inline]
     fn next_back(&mut self) -> Option<(A, B)> {
-        let (a_sz, a_upper) = self.a.size_hint();
-        let (b_sz, b_upper) = self.b.size_hint();
-        assert!(a_upper == Some(a_sz));
-        assert!(b_upper == Some(b_sz));
-        if a_sz < b_sz {
-            for _ in range(0, b_sz - a_sz) { self.b.next_back(); }
-        } else if a_sz > b_sz {
-            for _ in range(0, a_sz - b_sz) { self.a.next_back(); }
-        }
-        let (a_sz, _) = self.a.size_hint();
-        let (b_sz, _) = self.b.size_hint();
-        assert!(a_sz == b_sz);
+        let a_sz = self.a.len();
+        let b_sz = self.b.len();
+        if a_sz != b_sz {
+            // Adjust a, b to equal length
+            if a_sz > b_sz {
+                for _ in range(0, a_sz - b_sz) { self.a.next_back(); }
+            } else {
+                for _ in range(0, b_sz - a_sz) { self.b.next_back(); }
+            }
+        }
         match (self.a.next_back(), self.b.next_back()) {
             (Some(x), Some(y)) => Some((x, y)),
-            _ => None
+            (None, None) => None,
+            _ => unreachable!(),
         }
     }
 }
@@ -1395,9 +1398,8 @@ impl<A, T: ExactSize<A>> DoubleEndedIterator<(uint, A)> for Enumerate<T> {
     fn next_back(&mut self) -> Option<(uint, A)> {
         match self.iter.next_back() {
             Some(a) => {
-                let (lower, upper) = self.iter.size_hint();
-                assert!(upper == Some(lower));
-                Some((self.count + lower, a))
+                let len = self.iter.len();
+                Some((self.count + len, a))
             }
             _ => None
         }