Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redesign the std::iter::Step trait, tweak related iterator impls for ranges #43127

Closed
wants to merge 11 commits into from
Closed
Prev Previous commit
Next Next commit
Implement TrustedLen for ranges of all integer types
  • Loading branch information
SimonSapin committed Jul 24, 2017
commit c0b4440309cd971fcbda9611f9419906f715ab81
21 changes: 19 additions & 2 deletions src/libcore/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ macro_rules! step_integer_impls {
impl Step for $narrower_unsigned {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
// NOTE: the safety of `unsafe impl TrustedLen` depends on
// this being correct!
if *start < *end {
// This relies on $narrower_unsigned <= usize
Some((*end - *start) as usize)
Expand Down Expand Up @@ -92,6 +94,8 @@ macro_rules! step_integer_impls {
impl Step for $narrower_signed {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
// NOTE: the safety of `unsafe impl TrustedLen` depends on
// this being correct!
if *start < *end {
// This relies on $narrower_signed <= usize
//
Expand Down Expand Up @@ -156,6 +160,8 @@ macro_rules! step_integer_impls {
impl Step for $wider_unsigned {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
// NOTE: the safety of `unsafe impl TrustedLen` depends on
// this being correct!
if *start < *end {
usize::try_from(*end - *start).ok()
} else {
Expand All @@ -180,6 +186,8 @@ macro_rules! step_integer_impls {
impl Step for $wider_signed {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
// NOTE: the safety of `unsafe impl TrustedLen` depends on
// this being correct!
if *start < *end {
match end.checked_sub(*start) {
Some(diff) => usize::try_from(diff).ok(),
Expand Down Expand Up @@ -274,6 +282,7 @@ impl<A: Step> Iterator for ops::Range<A> {

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// NOTE: the safety of `unsafe impl TrustedLen` depends on this being correct!
match Step::steps_between(&self.start, &self.end) {
Some(hint) => (hint, Some(hint)),
None => (0, None)
Expand Down Expand Up @@ -306,8 +315,14 @@ range_incl_exact_iter_impl!(u8 u16 i8 i16);
//
// They need to guarantee that .size_hint() is either exact, or that
// the upper bound is None when it does not fit the type limits.
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
range_trusted_len_impl! {
usize u8 u16 u32 u64 u128
isize i8 i16 i32 i64 i128
}
range_incl_trusted_len_impl! {
usize u8 u16 u32 u64 u128
isize i8 i16 i32 i64 i128
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
Expand Down Expand Up @@ -387,6 +402,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// NOTE: the safety of `unsafe impl TrustedLen` depends on this being correct!

if !(self.start <= self.end) {
return (0, Some(0));
}
Expand Down