]> git.lizzy.rs Git - rust.git/commitdiff
Fix std::ops::Range size_hint and ExactSizeIterator impls
authorUlrik Sverdrup <root@localhost>
Sat, 7 Feb 2015 23:17:04 +0000 (00:17 +0100)
committerUlrik Sverdrup <root@localhost>
Sat, 7 Feb 2015 23:17:04 +0000 (00:17 +0100)
When self.start > self.end, these iterators simply return None,
so we adjust the size_hint to just return zero in this case.

Certain optimizations can be implemented in and outside libstd if we
know we can trust the size_hint for all inputs to for example
Range<usize>.

This corrects the ExactSizeIterator implementations, which IMO were
unsound and incorrect previously, since they allowed a range like (2..1)
to return a size_hint of -1us in when debug assertions are turned off.

src/libcore/iter.rs
src/libcoretest/iter.rs

index f3b42e4f0a5775db7c8c6d0deca663e3b368a59f..fa6719a0312c07b24607afbe749163c7d46a803d 100644 (file)
@@ -2646,13 +2646,7 @@ fn next(&mut self) -> Option<A> {
 macro_rules! range_exact_iter_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl ExactSizeIterator for ::ops::Range<$t> {
-            #[inline]
-            fn len(&self) -> usize {
-                debug_assert!(self.end >= self.start);
-                (self.end - self.start) as usize
-            }
-        }
+        impl ExactSizeIterator for ::ops::Range<$t> { }
     )*)
 }
 
@@ -2673,9 +2667,12 @@ fn next(&mut self) -> Option<A> {
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        debug_assert!(self.end >= self.start);
-        let hint = (self.end - self.start).to_uint();
-        (hint.unwrap_or(0), hint)
+        if self.start >= self.end {
+            (0, Some(0))
+        } else {
+            let length = (self.end - self.start).to_uint();
+            (length.unwrap_or(0), length)
+        }
     }
 }
 
index c9cdf50fdbd085df979e2fae0c6fc51244399891..3f8e330b332b8806570069fa615d0fea9487fd5f 100644 (file)
@@ -756,6 +756,7 @@ fn test_range() {
     // this test is only meaningful when sizeof uint < sizeof u64
     assert_eq!((uint::MAX - 1..uint::MAX).size_hint(), (1, Some(1)));
     assert_eq!((-10..-1).size_hint(), (9, Some(9)));
+    assert_eq!((-1..-10).size_hint(), (0, Some(0)));
 }
 
 #[test]