about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-02-10 08:41:48 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-02-10 08:41:48 -0800
commit24c92134ea8e51aeb2264f171eb2847b1909fc3e (patch)
treec3c76e20735e73f0dd5da4540e2b81514dbbf1e0
parent6e6bea6e074afb8c84c939a83b884585345ecf4f (diff)
parent4f61e160326676cdcce94b9d5bca7d88c5f40ee9 (diff)
downloadrust-24c92134ea8e51aeb2264f171eb2847b1909fc3e.tar.gz
rust-24c92134ea8e51aeb2264f171eb2847b1909fc3e.zip
rollup merge of #22065: bluss/range-size-hint
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.
-rw-r--r--src/libcore/iter.rs17
-rw-r--r--src/libcoretest/iter.rs1
2 files changed, 8 insertions, 10 deletions
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 5df64cfaada..18d68836f29 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -2646,13 +2646,7 @@ impl<A: Int> Iterator for RangeStepInclusive<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 @@ impl<A: Int> Iterator for ::ops::Range<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)
+        }
     }
 }
 
diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs
index c9cdf50fdbd..3f8e330b332 100644
--- a/src/libcoretest/iter.rs
+++ b/src/libcoretest/iter.rs
@@ -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]