From 680ebf7b16ff402e3c636a037448324517aca37a Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 4 Jan 2018 00:17:36 +0000 Subject: [PATCH 1/8] Add min and max specialisations for RangeInclusive --- src/libcore/iter/range.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index e9aee4a4676de..19a76302f178a 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -367,6 +367,16 @@ impl Iterator for ops::RangeInclusive { self.end.replace_zero(); None } + + #[inline] + fn min(self) -> Option { + Some(self.start) + } + + #[inline] + fn max(self) -> Option { + Some(self.end) + } } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] From 3d9c36fbf502100a46018119f73b70b89889de17 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 4 Jan 2018 00:58:41 +0000 Subject: [PATCH 2/8] Add min specialisation for RangeFrom and last for RangeInclusive --- src/libcore/iter/range.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 19a76302f178a..280f0eafcf026 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -305,6 +305,11 @@ impl Iterator for ops::RangeFrom { self.start = plus_n.add_one(); Some(plus_n) } + + #[inline] + fn min(self) -> Option { + Some(self.start) + } } #[unstable(feature = "fused", issue = "35602")] @@ -368,6 +373,11 @@ impl Iterator for ops::RangeInclusive { None } + #[inline] + fn last(self) -> Option { + Some(self.end) + } + #[inline] fn min(self) -> Option { Some(self.start) From 29e6b1034be69b68f6a972d15b183badb4cfe888 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 4 Jan 2018 01:51:18 +0000 Subject: [PATCH 3/8] Add max and sum specialisations for Range --- src/libcore/iter/range.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 280f0eafcf026..ecc288d07fcef 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -13,7 +13,7 @@ use mem; use ops::{self, Add, Sub}; use usize; -use super::{FusedIterator, TrustedLen}; +use super::{FusedIterator, TrustedLen, Sum}; /// Objects that can be stepped over in both directions. /// @@ -177,6 +177,20 @@ step_impl_signed!([i64: u64]); step_impl_no_between!(u64 i64); step_impl_no_between!(u128 i128); +macro_rules! range_inc_iter_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Iterator for ops::RangeInclusive<$t> { + #[inline] + fn sum(self) -> S where S: Sum<$t> { + let a = self.start; + let b = self.end; + S::sum(super::once((a + b) * (1 + b - a) / 2)) + } + } + )*) +} + macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] @@ -251,8 +265,18 @@ impl Iterator for ops::Range { self.start = self.end.clone(); None } + + #[inline] + fn max(self) -> Option { + if self.start != self.end { + Some(self.end.sub_one()) + } else { None } + } } +// These macros generate specialisations for `Iterator` methods for efficiency purposes. +range_inc_iter_impl!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); + // These macros generate `ExactSizeIterator` impls for various range types. // Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded // because they cannot guarantee having a length <= usize::MAX, which is From 087bffa78cf62b62d3cafbe5a77ed675efccb7e6 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 4 Jan 2018 12:36:43 +0000 Subject: [PATCH 4/8] Remove RangeInclusive::sum --- src/libcore/iter/range.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index ecc288d07fcef..4aec70a86e08f 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -13,7 +13,7 @@ use mem; use ops::{self, Add, Sub}; use usize; -use super::{FusedIterator, TrustedLen, Sum}; +use super::{FusedIterator, TrustedLen}; /// Objects that can be stepped over in both directions. /// @@ -177,20 +177,6 @@ step_impl_signed!([i64: u64]); step_impl_no_between!(u64 i64); step_impl_no_between!(u128 i128); -macro_rules! range_inc_iter_impl { - ($($t:ty)*) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl Iterator for ops::RangeInclusive<$t> { - #[inline] - fn sum(self) -> S where S: Sum<$t> { - let a = self.start; - let b = self.end; - S::sum(super::once((a + b) * (1 + b - a) / 2)) - } - } - )*) -} - macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] @@ -274,9 +260,6 @@ impl Iterator for ops::Range { } } -// These macros generate specialisations for `Iterator` methods for efficiency purposes. -range_inc_iter_impl!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); - // These macros generate `ExactSizeIterator` impls for various range types. // Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded // because they cannot guarantee having a length <= usize::MAX, which is From f3baa8572917b6c326605853685a195f99c3b874 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 4 Jan 2018 12:37:00 +0000 Subject: [PATCH 5/8] Add tests for specialised Range iter methods --- src/libcore/tests/iter.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 5cac5b26d88bd..71a75115d8613 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1352,6 +1352,38 @@ fn test_range_step() { assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } +#[test] +fn test_range_max() { + assert_eq!((0..100).max(), Some(99)); + assert_eq!((-20..-10).max(), Some(-11)); + assert_eq!((1..1).max(), None); +} + +#[test] +fn test_range_from_min() { + assert_eq!((0..).min(), Some(0)); + assert_eq!((-20..).min(), Some(-20)); + assert_eq!((20..).min(), Some(20)); +} + +#[test] +fn test_range_inc_last_max() { + assert_eq!((0..=20).last(), Some(20)); + assert_eq!((-20..=0).last(), Some(0)); + assert_eq!((5..=5).last(), Some(5)); + + assert_eq!((0..=20).max(), Some(20)); + assert_eq!((-20..=0).max(), Some(0)); + assert_eq!((5..=5).max(), Some(5)); +} + +#[test] +fn test_range_inc_min() { + assert_eq!((0..=20).min(), Some(0)); + assert_eq!((-20..=0).min(), Some(-20)); + assert_eq!((5..=5).min(), Some(5)); +} + #[test] fn test_repeat() { let mut it = repeat(42); From 439beab41fb5162b26c075a7d7cb28662ba0ab7b Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 4 Jan 2018 15:03:50 +0000 Subject: [PATCH 6/8] Remove min from RangeFrom --- src/libcore/iter/range.rs | 5 ----- src/libcore/tests/iter.rs | 7 ------- 2 files changed, 12 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 4aec70a86e08f..03cc5a03cff2d 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -312,11 +312,6 @@ impl Iterator for ops::RangeFrom { self.start = plus_n.add_one(); Some(plus_n) } - - #[inline] - fn min(self) -> Option { - Some(self.start) - } } #[unstable(feature = "fused", issue = "35602")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 71a75115d8613..c75417f8de92b 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1359,13 +1359,6 @@ fn test_range_max() { assert_eq!((1..1).max(), None); } -#[test] -fn test_range_from_min() { - assert_eq!((0..).min(), Some(0)); - assert_eq!((-20..).min(), Some(-20)); - assert_eq!((20..).min(), Some(20)); -} - #[test] fn test_range_inc_last_max() { assert_eq!((0..=20).last(), Some(20)); From c23d4500fdb865040a584da24122592b25feb09a Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 5 Jan 2018 18:57:10 +0000 Subject: [PATCH 7/8] Fix behaviour after iterator exhaustion --- src/libcore/iter/range.rs | 12 +++++++++--- src/libcore/tests/iter.rs | 13 +++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 03cc5a03cff2d..7a38e0cf7cc43 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -377,17 +377,23 @@ impl Iterator for ops::RangeInclusive { #[inline] fn last(self) -> Option { - Some(self.end) + if self.start <= self.end { + Some(self.end) + } else { None } } #[inline] fn min(self) -> Option { - Some(self.start) + if self.start <= self.end { + Some(self.start) + } else { None } } #[inline] fn max(self) -> Option { - Some(self.end) + if self.start <= self.end { + Some(self.end) + } else { None } } } diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index c75417f8de92b..9cbec8f9e6e88 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1360,21 +1360,30 @@ fn test_range_max() { } #[test] -fn test_range_inc_last_max() { +fn test_range_inclusive_last_max() { assert_eq!((0..=20).last(), Some(20)); assert_eq!((-20..=0).last(), Some(0)); assert_eq!((5..=5).last(), Some(5)); + let mut r = 10..=10; + r.next(); + assert_eq!(r.last(), None); assert_eq!((0..=20).max(), Some(20)); assert_eq!((-20..=0).max(), Some(0)); assert_eq!((5..=5).max(), Some(5)); + let mut r = 10..=10; + r.next(); + assert_eq!(r.max(), None); } #[test] -fn test_range_inc_min() { +fn test_range_inclusive_min() { assert_eq!((0..=20).min(), Some(0)); assert_eq!((-20..=0).min(), Some(-20)); assert_eq!((5..=5).min(), Some(5)); + let mut r = 10..=10; + r.next(); + assert_eq!(r.min(), None); } #[test] From 2d8334358aeda76428ec1f841ec31ab3579325e0 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 6 Jan 2018 22:14:02 +0000 Subject: [PATCH 8/8] Use `next` and `next_back` --- src/libcore/iter/range.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 7a38e0cf7cc43..d6c1420a03c29 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -253,10 +253,8 @@ impl Iterator for ops::Range { } #[inline] - fn max(self) -> Option { - if self.start != self.end { - Some(self.end.sub_one()) - } else { None } + fn max(mut self) -> Option { + self.next_back() } } @@ -376,24 +374,18 @@ impl Iterator for ops::RangeInclusive { } #[inline] - fn last(self) -> Option { - if self.start <= self.end { - Some(self.end) - } else { None } + fn last(mut self) -> Option { + self.next_back() } #[inline] - fn min(self) -> Option { - if self.start <= self.end { - Some(self.start) - } else { None } + fn min(mut self) -> Option { + self.next() } #[inline] - fn max(self) -> Option { - if self.start <= self.end { - Some(self.end) - } else { None } + fn max(mut self) -> Option { + self.next_back() } }