From dbed18ca20f14a1fe3c8a1e02071c8e8dd7476c5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 5 Jul 2017 23:49:33 +0200 Subject: [PATCH 1/7] Remove unused Add bounds in iterator for ranges impls. --- src/libcore/iter/range.rs | 31 ++++++++----------------------- src/test/compile-fail/range-1.rs | 1 - 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 1dad815794895..11a8f8f7ee6b0 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -277,9 +277,7 @@ macro_rules! range_incl_trusted_len_impl { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::Range where - for<'a> &'a A: Add<&'a A, Output = A> -{ +impl Iterator for ops::Range { type Item = A; #[inline] @@ -317,10 +315,7 @@ 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); #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range where - for<'a> &'a A: Add<&'a A, Output = A>, - for<'a> &'a A: Sub<&'a A, Output = A> -{ +impl DoubleEndedIterator for ops::Range { #[inline] fn next_back(&mut self) -> Option { if self.start < self.end { @@ -333,13 +328,10 @@ impl DoubleEndedIterator for ops::Range where } #[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for ops::Range - where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} +impl FusedIterator for ops::Range {} #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::RangeFrom where - for<'a> &'a A: Add<&'a A, Output = A> -{ +impl Iterator for ops::RangeFrom { type Item = A; #[inline] @@ -356,13 +348,10 @@ impl Iterator for ops::RangeFrom where } #[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for ops::RangeFrom - where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} +impl FusedIterator for ops::RangeFrom {} #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl Iterator for ops::RangeInclusive where - for<'a> &'a A: Add<&'a A, Output = A> -{ +impl Iterator for ops::RangeInclusive { type Item = A; #[inline] @@ -397,10 +386,7 @@ impl Iterator for ops::RangeInclusive where } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] -impl DoubleEndedIterator for ops::RangeInclusive where - for<'a> &'a A: Add<&'a A, Output = A>, - for<'a> &'a A: Sub<&'a A, Output = A> -{ +impl DoubleEndedIterator for ops::RangeInclusive { #[inline] fn next_back(&mut self) -> Option { use cmp::Ordering::*; @@ -421,5 +407,4 @@ impl DoubleEndedIterator for ops::RangeInclusive where } #[unstable(feature = "fused", issue = "35602")] -impl FusedIterator for ops::RangeInclusive - where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} +impl FusedIterator for ops::RangeInclusive {} diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs index dc6833163a478..58794e3b35d53 100644 --- a/src/test/compile-fail/range-1.rs +++ b/src/test/compile-fail/range-1.rs @@ -18,7 +18,6 @@ pub fn main() { // Bool => does not implement iterator. for i in false..true {} //~^ ERROR `bool: std::iter::Step` is not satisfied - //~^^ ERROR `for<'a> &'a bool: std::ops::Add` is not satisfied // Unsized type. let arr: &[_] = &[1, 2, 3]; From 4b2f40dfdf5ff2bcbcc8105246a8c32054c40cb7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 5 Jul 2017 23:54:08 +0200 Subject: [PATCH 2/7] Remove unused Step methods --- src/libcore/iter/range.rs | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 11a8f8f7ee6b0..db3fc1155c328 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -22,9 +22,6 @@ use super::{FusedIterator, TrustedLen}; reason = "likely to be replaced by finer-grained traits", issue = "42168")] pub trait Step: PartialOrd + Sized { - /// Steps `self` if possible. - fn step(&self, by: &Self) -> Option; - /// Returns the number of steps between two step objects. The count is /// inclusive of `start` and exclusive of `end`. /// @@ -35,9 +32,6 @@ pub trait Step: PartialOrd + Sized { /// Same as `steps_between`, but with a `by` of 1 fn steps_between_by_one(start: &Self, end: &Self) -> Option; - /// Tests whether this step is negative or not (going backwards) - fn is_negative(&self) -> bool; - /// Replaces this step with `1`, returning itself fn replace_one(&mut self) -> Self; @@ -57,10 +51,6 @@ macro_rules! step_impl_unsigned { reason = "likely to be replaced by finer-grained traits", issue = "42168")] impl Step for $t { - #[inline] - fn step(&self, by: &$t) -> Option<$t> { - (*self).checked_add(*by) - } #[inline] #[allow(trivial_numeric_casts)] fn steps_between(start: &$t, end: &$t, by: &$t) -> Option { @@ -79,11 +69,6 @@ macro_rules! step_impl_unsigned { } } - #[inline] - fn is_negative(&self) -> bool { - false - } - #[inline] fn replace_one(&mut self) -> Self { mem::replace(self, 1) @@ -117,10 +102,6 @@ macro_rules! step_impl_signed { reason = "likely to be replaced by finer-grained traits", issue = "42168")] impl Step for $t { - #[inline] - fn step(&self, by: &$t) -> Option<$t> { - (*self).checked_add(*by) - } #[inline] #[allow(trivial_numeric_casts)] fn steps_between(start: &$t, end: &$t, by: &$t) -> Option { @@ -150,11 +131,6 @@ macro_rules! step_impl_signed { } } - #[inline] - fn is_negative(&self) -> bool { - *self < 0 - } - #[inline] fn replace_one(&mut self) -> Self { mem::replace(self, 1) @@ -189,21 +165,11 @@ macro_rules! step_impl_no_between { reason = "likely to be replaced by finer-grained traits", issue = "42168")] impl Step for $t { - #[inline] - fn step(&self, by: &$t) -> Option<$t> { - (*self).checked_add(*by) - } #[inline] fn steps_between(_a: &$t, _b: &$t, _by: &$t) -> Option { None } - #[inline] - #[allow(unused_comparisons)] - fn is_negative(&self) -> bool { - *self < 0 - } - #[inline] fn replace_one(&mut self) -> Self { mem::replace(self, 1) From d1ec6c22d1895eb42fbf20bd9b577b6a721c6b5f Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 6 Jul 2017 00:10:40 +0200 Subject: [PATCH 3/7] Remove Step::steps_between, rename steps_between_by_one to steps_between --- src/libcore/iter/range.rs | 61 +++++++-------------------------------- 1 file changed, 10 insertions(+), 51 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index db3fc1155c328..4d6eca06db2a0 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -27,10 +27,7 @@ pub trait Step: PartialOrd + Sized { /// /// Returns `None` if it is not possible to calculate `steps_between` /// without overflow. - fn steps_between(start: &Self, end: &Self, by: &Self) -> Option; - - /// Same as `steps_between`, but with a `by` of 1 - fn steps_between_by_one(start: &Self, end: &Self) -> Option; + fn steps_between(start: &Self, end: &Self) -> Option; /// Replaces this step with `1`, returning itself fn replace_one(&mut self) -> Self; @@ -53,17 +50,10 @@ macro_rules! step_impl_unsigned { impl Step for $t { #[inline] #[allow(trivial_numeric_casts)] - fn steps_between(start: &$t, end: &$t, by: &$t) -> Option { - if *by == 0 { return None; } + fn steps_between(start: &$t, end: &$t) -> Option { if *start < *end { // Note: We assume $t <= usize here - let diff = (*end - *start) as usize; - let by = *by as usize; - if diff % by > 0 { - Some(diff / by + 1) - } else { - Some(diff / by) - } + Some((*end - *start) as usize) } else { Some(0) } @@ -88,11 +78,6 @@ macro_rules! step_impl_unsigned { fn sub_one(&self) -> Self { Sub::sub(*self, 1) } - - #[inline] - fn steps_between_by_one(start: &Self, end: &Self) -> Option { - Self::steps_between(start, end, &1) - } } )*) } @@ -104,30 +89,14 @@ macro_rules! step_impl_signed { impl Step for $t { #[inline] #[allow(trivial_numeric_casts)] - fn steps_between(start: &$t, end: &$t, by: &$t) -> Option { - if *by == 0 { return None; } - let diff: usize; - let by_u: usize; - if *by > 0 { - if *start >= *end { - return Some(0); - } + fn steps_between(start: &$t, end: &$t) -> Option { + 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. - diff = (*end as isize).wrapping_sub(*start as isize) as usize; - by_u = *by as usize; - } else { - if *start <= *end { - return Some(0); - } - diff = (*start as isize).wrapping_sub(*end as isize) as usize; - by_u = (*by as isize).wrapping_mul(-1) as usize; - } - if diff % by_u > 0 { - Some(diff / by_u + 1) + Some((*end as isize).wrapping_sub(*start as isize) as usize) } else { - Some(diff / by_u) + Some(0) } } @@ -150,11 +119,6 @@ macro_rules! step_impl_signed { fn sub_one(&self) -> Self { Sub::sub(*self, 1) } - - #[inline] - fn steps_between_by_one(start: &Self, end: &Self) -> Option { - Self::steps_between(start, end, &1) - } } )*) } @@ -166,7 +130,7 @@ macro_rules! step_impl_no_between { issue = "42168")] impl Step for $t { #[inline] - fn steps_between(_a: &$t, _b: &$t, _by: &$t) -> Option { + fn steps_between(_start: &Self, _end: &Self) -> Option { None } @@ -189,11 +153,6 @@ macro_rules! step_impl_no_between { fn sub_one(&self) -> Self { Sub::sub(*self, 1) } - - #[inline] - fn steps_between_by_one(start: &Self, end: &Self) -> Option { - Self::steps_between(start, end, &1) - } } )*) } @@ -259,7 +218,7 @@ impl Iterator for ops::Range { #[inline] fn size_hint(&self) -> (usize, Option) { - match Step::steps_between_by_one(&self.start, &self.end) { + match Step::steps_between(&self.start, &self.end) { Some(hint) => (hint, Some(hint)), None => (0, None) } @@ -344,7 +303,7 @@ impl Iterator for ops::RangeInclusive { return (0, Some(0)); } - match Step::steps_between_by_one(&self.start, &self.end) { + match Step::steps_between(&self.start, &self.end) { Some(hint) => (hint.saturating_add(1), hint.checked_add(1)), None => (0, None), } From 8e8fd024198a059b759ae8472d6a29ba6a206b01 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 6 Jul 2017 00:32:54 +0200 Subject: [PATCH 4/7] Factorize some macros in iter/range.rs --- src/libcore/iter/range.rs | 85 +++++++++++++-------------------------- 1 file changed, 28 insertions(+), 57 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 4d6eca06db2a0..9831019191291 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -42,6 +42,31 @@ pub trait Step: PartialOrd + Sized { fn sub_one(&self) -> Self; } +// These are still macro-generated because the integer literals resolve to different types. +macro_rules! step_identical_methods { + () => { + #[inline] + fn replace_one(&mut self) -> Self { + mem::replace(self, 1) + } + + #[inline] + fn replace_zero(&mut self) -> Self { + mem::replace(self, 0) + } + + #[inline] + fn add_one(&self) -> Self { + Add::add(*self, 1) + } + + #[inline] + fn sub_one(&self) -> Self { + Sub::sub(*self, 1) + } + } +} + macro_rules! step_impl_unsigned { ($($t:ty)*) => ($( #[unstable(feature = "step_trait", @@ -59,25 +84,7 @@ macro_rules! step_impl_unsigned { } } - #[inline] - fn replace_one(&mut self) -> Self { - mem::replace(self, 1) - } - - #[inline] - fn replace_zero(&mut self) -> Self { - mem::replace(self, 0) - } - - #[inline] - fn add_one(&self) -> Self { - Add::add(*self, 1) - } - - #[inline] - fn sub_one(&self) -> Self { - Sub::sub(*self, 1) - } + step_identical_methods!(); } )*) } @@ -100,25 +107,7 @@ macro_rules! step_impl_signed { } } - #[inline] - fn replace_one(&mut self) -> Self { - mem::replace(self, 1) - } - - #[inline] - fn replace_zero(&mut self) -> Self { - mem::replace(self, 0) - } - - #[inline] - fn add_one(&self) -> Self { - Add::add(*self, 1) - } - - #[inline] - fn sub_one(&self) -> Self { - Sub::sub(*self, 1) - } + step_identical_methods!(); } )*) } @@ -134,25 +123,7 @@ macro_rules! step_impl_no_between { None } - #[inline] - fn replace_one(&mut self) -> Self { - mem::replace(self, 1) - } - - #[inline] - fn replace_zero(&mut self) -> Self { - mem::replace(self, 0) - } - - #[inline] - fn add_one(&self) -> Self { - Add::add(*self, 1) - } - - #[inline] - fn sub_one(&self) -> Self { - Sub::sub(*self, 1) - } + step_identical_methods!(); } )*) } From de4afc6797a7a3b4973cbcb897e25a3a0213516b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 6 Jul 2017 01:14:20 +0200 Subject: [PATCH 5/7] Implement O(1)-time Iterator::nth for Range* --- src/libcore/iter/range.rs | 89 +++++++++++++++++-- .../run-pass/impl-trait/example-calendar.rs | 18 ++-- 2 files changed, 89 insertions(+), 18 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9831019191291..32c32e327eb2d 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use convert::TryFrom; use mem; use ops::{self, Add, Sub}; use usize; @@ -21,7 +22,7 @@ use super::{FusedIterator, TrustedLen}; #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", issue = "42168")] -pub trait Step: PartialOrd + Sized { +pub trait Step: Clone + PartialOrd + Sized { /// Returns the number of steps between two step objects. The count is /// inclusive of `start` and exclusive of `end`. /// @@ -40,6 +41,9 @@ pub trait Step: PartialOrd + Sized { /// Subtracts one to this step, returning the result fn sub_one(&self) -> Self; + + /// Add an usize, returning None on overflow + fn add_usize(&self, n: usize) -> Option; } // These are still macro-generated because the integer literals resolve to different types. @@ -84,12 +88,20 @@ macro_rules! step_impl_unsigned { } } + #[inline] + fn add_usize(&self, n: usize) -> Option { + match <$t>::try_from(n) { + Ok(n_as_t) => self.checked_add(n_as_t), + Err(_) => None, + } + } + step_identical_methods!(); } )*) } macro_rules! step_impl_signed { - ($($t:ty)*) => ($( + ($( [$t:ty : $unsigned:ty] )*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", issue = "42168")] @@ -107,6 +119,24 @@ macro_rules! step_impl_signed { } } + #[inline] + fn add_usize(&self, n: usize) -> Option { + match <$unsigned>::try_from(n) { + Ok(n_as_unsigned) => { + // Wrapping in unsigned space handles cases like + // `-120_i8.add_usize(200) == Some(80_i8)`, + // even though 200_usize is out of range for i8. + let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t; + if wrapped >= *self { + Some(wrapped) + } else { + None // Addition overflowed + } + } + Err(_) => None, + } + } + step_identical_methods!(); } )*) @@ -123,17 +153,22 @@ macro_rules! step_impl_no_between { None } + #[inline] + fn add_usize(&self, n: usize) -> Option { + self.checked_add(n as $t) + } + step_identical_methods!(); } )*) } step_impl_unsigned!(usize u8 u16 u32); -step_impl_signed!(isize i8 i16 i32); +step_impl_signed!([isize: usize] [i8: u8] [i16: u16] [i32: u32]); #[cfg(target_pointer_width = "64")] step_impl_unsigned!(u64); #[cfg(target_pointer_width = "64")] -step_impl_signed!(i64); +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"))] @@ -194,6 +229,19 @@ impl Iterator for ops::Range { None => (0, None) } } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = self.start.add_usize(n) { + if plus_n < self.end { + self.start = plus_n.add_one(); + return Some(plus_n) + } + } + + self.start = self.end.clone(); + None + } } // These macros generate `ExactSizeIterator` impls for various range types. @@ -211,7 +259,7 @@ 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); #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range { +impl DoubleEndedIterator for ops::Range { #[inline] fn next_back(&mut self) -> Option { if self.start < self.end { @@ -241,6 +289,13 @@ impl Iterator for ops::RangeFrom { fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let plus_n = self.start.add_usize(n).expect("overflow in RangeFrom::nth"); + self.start = plus_n.add_one(); + Some(plus_n) + } } #[unstable(feature = "fused", issue = "35602")] @@ -279,6 +334,30 @@ impl Iterator for ops::RangeInclusive { None => (0, None), } } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + if let Some(plus_n) = self.start.add_usize(n) { + use cmp::Ordering::*; + + match plus_n.partial_cmp(&self.end) { + Some(Less) => { + self.start = plus_n.add_one(); + return Some(plus_n) + } + Some(Equal) => { + self.start.replace_one(); + self.end.replace_zero(); + return Some(plus_n) + } + _ => {} + } + } + + self.start.replace_one(); + self.end.replace_zero(); + None + } } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs index 2a9af26881c77..84d86cfdf65a4 100644 --- a/src/test/run-pass/impl-trait/example-calendar.rs +++ b/src/test/run-pass/impl-trait/example-calendar.rs @@ -162,22 +162,10 @@ impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate { } impl std::iter::Step for NaiveDate { - fn step(&self, by: &Self) -> Option { - Some(self + by) - } - - fn steps_between(_: &Self, _: &Self, _: &Self) -> Option { - unimplemented!() - } - - fn steps_between_by_one(_: &Self, _: &Self) -> Option { + fn steps_between(_: &Self, _: &Self) -> Option { unimplemented!() } - fn is_negative(&self) -> bool { - false - } - fn replace_one(&mut self) -> Self { mem::replace(self, NaiveDate(0, 0, 1)) } @@ -193,6 +181,10 @@ impl std::iter::Step for NaiveDate { fn sub_one(&self) -> Self { unimplemented!() } + + fn add_usize(&self, _: usize) -> Option { + unimplemented!() + } } #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] From 7a40307a7ca44d8ff4035c59022647cddc5b6699 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 6 Jul 2017 17:13:29 +0200 Subject: [PATCH 6/7] Add tests for Range*::nth --- src/libcore/tests/iter.rs | 49 +++++++++++++++++++++++++++++++++++++++ src/libcore/tests/lib.rs | 2 ++ 2 files changed, 51 insertions(+) diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 14f0260f57129..748eac10ac0bb 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1076,6 +1076,55 @@ fn test_range() { (isize::MAX as usize + 2, Some(isize::MAX as usize + 2))); } +#[test] +fn test_range_nth() { + assert_eq!((10..15).nth(0), Some(10)); + assert_eq!((10..15).nth(1), Some(11)); + assert_eq!((10..15).nth(4), Some(14)); + assert_eq!((10..15).nth(5), None); + + let mut r = 10..20; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 13..20); + assert_eq!(r.nth(2), Some(15)); + assert_eq!(r, 16..20); + assert_eq!(r.nth(10), None); + assert_eq!(r, 20..20); +} + +#[test] +fn test_range_from_nth() { + assert_eq!((10..).nth(0), Some(10)); + assert_eq!((10..).nth(1), Some(11)); + assert_eq!((10..).nth(4), Some(14)); + + let mut r = 10..; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 13..); + assert_eq!(r.nth(2), Some(15)); + assert_eq!(r, 16..); + assert_eq!(r.nth(10), Some(26)); + assert_eq!(r, 27..); +} + +#[test] +fn test_range_inclusive_nth() { + assert_eq!((10...15).nth(0), Some(10)); + assert_eq!((10...15).nth(1), Some(11)); + assert_eq!((10...15).nth(5), Some(15)); + assert_eq!((10...15).nth(6), None); + + let mut r = 10_u8...20; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 13...20); + assert_eq!(r.nth(2), Some(15)); + assert_eq!(r, 16...20); + assert_eq!(r.is_empty(), false); + assert_eq!(r.nth(10), None); + assert_eq!(r.is_empty(), true); + assert_eq!(r, 1...0); // We may not want to document/promise this detail +} + #[test] fn test_range_step() { #![allow(deprecated)] diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 8d3e367d2379a..26e4c21dc8f4d 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -18,12 +18,14 @@ #![feature(core_private_diy_float)] #![feature(dec2flt)] #![feature(decode_utf8)] +#![feature(exact_size_is_empty)] #![feature(fixed_size_array)] #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(iterator_step_by)] #![feature(i128_type)] #![feature(inclusive_range)] +#![feature(inclusive_range_syntax)] #![feature(iter_rfind)] #![feature(libc)] #![feature(nonzero)] From e9a61eeb0434aabc1874c768eebc8bc7a68c6659 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 6 Jul 2017 18:13:44 +0200 Subject: [PATCH 7/7] Add tests for reaching the end of RangeInclusive as an iterator --- src/libcore/tests/iter.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 748eac10ac0bb..a1249a5f22cf7 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1076,6 +1076,26 @@ fn test_range() { (isize::MAX as usize + 2, Some(isize::MAX as usize + 2))); } +#[test] +fn test_range_inclusive_exhaustion() { + let mut r = 10...10; + assert_eq!(r.next(), Some(10)); + assert_eq!(r, 1...0); + + let mut r = 10...10; + assert_eq!(r.next_back(), Some(10)); + assert_eq!(r, 1...0); + + let mut r = 10...12; + assert_eq!(r.nth(2), Some(12)); + assert_eq!(r, 1...0); + + let mut r = 10...12; + assert_eq!(r.nth(5), None); + assert_eq!(r, 1...0); + +} + #[test] fn test_range_nth() { assert_eq!((10..15).nth(0), Some(10));