diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-02-10 08:41:48 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-02-10 08:41:48 -0800 |
| commit | 24c92134ea8e51aeb2264f171eb2847b1909fc3e (patch) | |
| tree | c3c76e20735e73f0dd5da4540e2b81514dbbf1e0 | |
| parent | 6e6bea6e074afb8c84c939a83b884585345ecf4f (diff) | |
| parent | 4f61e160326676cdcce94b9d5bca7d88c5f40ee9 (diff) | |
| download | rust-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.rs | 17 | ||||
| -rw-r--r-- | src/libcoretest/iter.rs | 1 |
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] |
