diff options
| author | bors <bors@rust-lang.org> | 2018-01-11 12:22:54 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-01-11 12:22:54 +0000 |
| commit | 73ac5d6a80f26c692f1e084b72d69637d7de2c8c (patch) | |
| tree | d15437596327bad850bf1ef4f07d3bc5abe26005 | |
| parent | 619ced057842a25f8700237a9c22a6f5c318a954 (diff) | |
| parent | 919d643b7953ea1b3b717d31f0735423d97b87ca (diff) | |
Auto merge of #47180 - varkor:range-iterator-overrides, r=alexcrichton
Add iterator method specialisations to Range* Add specialised implementations of `max` for `Range`, and `last`, `min` and `max` for `RangeInclusive`, all of which lead to significant advantages in the generated assembly on x86. Note that adding specialisations of `min` and `last` for `Range` led to no benefit, and adding `sum` for `Range` and `RangeInclusive` led to type inference issues (though this is possibly still worthwhile considering the performance gain). This addresses some of the concerns in #39975.
| -rw-r--r-- | src/libcore/iter/range.rs | 30 | ||||
| -rw-r--r-- | src/libcore/tests/iter.rs | 45 |
2 files changed, 75 insertions, 0 deletions
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index e9aee4a4676..66a76a24df4 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -251,6 +251,21 @@ impl<A: Step> Iterator for ops::Range<A> { self.start = self.end.clone(); None } + + #[inline] + fn last(mut self) -> Option<A> { + self.next_back() + } + + #[inline] + fn min(mut self) -> Option<A> { + self.next() + } + + #[inline] + fn max(mut self) -> Option<A> { + self.next_back() + } } // These macros generate `ExactSizeIterator` impls for various range types. @@ -367,6 +382,21 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> { self.end.replace_zero(); None } + + #[inline] + fn last(mut self) -> Option<A> { + self.next_back() + } + + #[inline] + fn min(mut self) -> Option<A> { + self.next() + } + + #[inline] + fn max(mut self) -> Option<A> { + self.next_back() + } } #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 5cac5b26d88..8997cf9c6bf 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1353,6 +1353,51 @@ fn test_range_step() { } #[test] +fn test_range_last_max() { + assert_eq!((0..20).last(), Some(19)); + assert_eq!((-20..0).last(), Some(-1)); + assert_eq!((5..5).last(), None); + + assert_eq!((0..20).max(), Some(19)); + assert_eq!((-20..0).max(), Some(-1)); + assert_eq!((5..5).max(), None); +} + +#[test] +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_min() { + assert_eq!((0..20).min(), Some(0)); + assert_eq!((-20..0).min(), Some(-20)); + assert_eq!((5..5).min(), None); +} + +#[test] +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] fn test_repeat() { let mut it = repeat(42); assert_eq!(it.next(), Some(42)); |
