about summary refs log tree commit diff
path: root/src/libcore/iter
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2019-03-25 21:12:53 -0700
committerJosh Stone <jistone@redhat.com>2019-03-26 10:13:48 -0700
commit01162d86c533cfb08221bb9475042ca94d1fd002 (patch)
treee6f0ab70e4169ddb797700643a2debfad846c44f /src/libcore/iter
parentd91b32b4dc9db066ab7deedbc51dc62ba597524b (diff)
downloadrust-01162d86c533cfb08221bb9475042ca94d1fd002.tar.gz
rust-01162d86c533cfb08221bb9475042ca94d1fd002.zip
Implement useful steps_between for all integers
We can use `usize::try_from` to convert steps from any size of integer.
This enables a meaningful `size_hint()` for larger ranges, rather than
always just `(0, None)`. Now they return the true `(len, Some(len))`
when it fits, otherwise `(usize::MAX, None)` for overflow.
Diffstat (limited to 'src/libcore/iter')
-rw-r--r--src/libcore/iter/range.rs57
1 files changed, 8 insertions, 49 deletions
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index e7efd9728b9..145fde0350e 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -68,11 +68,9 @@ macro_rules! step_impl_unsigned {
                    issue = "42168")]
         impl Step for $t {
             #[inline]
-            #[allow(trivial_numeric_casts)]
             fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                 if *start < *end {
-                    // Note: We assume $t <= usize here
-                    Some((*end - *start) as usize)
+                    usize::try_from(*end - *start).ok()
                 } else {
                     Some(0)
                 }
@@ -98,13 +96,11 @@ macro_rules! step_impl_signed {
                    issue = "42168")]
         impl Step for $t {
             #[inline]
-            #[allow(trivial_numeric_casts)]
             fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                 if *start < *end {
-                    // Note: We assume $t <= isize here
-                    // Use .wrapping_sub and cast to usize to compute the
-                    // difference that may not fit inside the range of isize.
-                    Some((*end as isize).wrapping_sub(*start as isize) as usize)
+                    // Use .wrapping_sub and cast to unsigned to compute the
+                    // difference that may not fit inside the range of $t.
+                    usize::try_from(end.wrapping_sub(*start) as $unsigned).ok()
                 } else {
                     Some(0)
                 }
@@ -134,46 +130,9 @@ macro_rules! step_impl_signed {
     )*)
 }
 
-macro_rules! step_impl_no_between {
-    ($($t:ty)*) => ($(
-        #[unstable(feature = "step_trait",
-                   reason = "likely to be replaced by finer-grained traits",
-                   issue = "42168")]
-        impl Step for $t {
-            #[inline]
-            fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
-                None
-            }
-
-            #[inline]
-            fn add_usize(&self, n: usize) -> Option<Self> {
-                self.checked_add(n as $t)
-            }
-
-            step_identical_methods!();
-        }
-    )*)
-}
-
-step_impl_unsigned!(usize u8 u16);
-#[cfg(not(target_pointer_width = "16"))]
-step_impl_unsigned!(u32);
-#[cfg(target_pointer_width = "16")]
-step_impl_no_between!(u32);
+step_impl_unsigned!(usize u8 u16 u32 u64 u128);
 step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
-#[cfg(not(target_pointer_width = "16"))]
-step_impl_signed!([i32: u32]);
-#[cfg(target_pointer_width = "16")]
-step_impl_no_between!(i32);
-#[cfg(target_pointer_width = "64")]
-step_impl_unsigned!(u64);
-#[cfg(target_pointer_width = "64")]
-step_impl_signed!([i64: u64]);
-// If the target pointer width is not 64-bits, we
-// assume here that it is less than 64-bits.
-#[cfg(not(target_pointer_width = "64"))]
-step_impl_no_between!(u64 i64);
-step_impl_no_between!(u128 i128);
+step_impl_signed!([i32: u32] [i64: u64] [i128: u128]);
 
 macro_rules! range_exact_iter_impl {
     ($($t:ty)*) => ($(
@@ -229,7 +188,7 @@ impl<A: Step> Iterator for ops::Range<A> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         match Step::steps_between(&self.start, &self.end) {
             Some(hint) => (hint, Some(hint)),
-            None => (0, None)
+            None => (usize::MAX, None)
         }
     }
 
@@ -350,7 +309,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
 
         match Step::steps_between(&self.start, &self.end) {
             Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
-            None => (0, None),
+            None => (usize::MAX, None),
         }
     }