diff options
| author | Josh Stone <jistone@redhat.com> | 2019-03-25 21:12:53 -0700 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2019-03-26 10:13:48 -0700 |
| commit | 01162d86c533cfb08221bb9475042ca94d1fd002 (patch) | |
| tree | e6f0ab70e4169ddb797700643a2debfad846c44f /src/libcore/iter | |
| parent | d91b32b4dc9db066ab7deedbc51dc62ba597524b (diff) | |
| download | rust-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.rs | 57 |
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), } } |
