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.
This commit is contained in:
commit
73ac5d6a80
@ -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")]
|
||||
|
@ -1352,6 +1352,51 @@ fn test_range_step() {
|
||||
assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
|
||||
}
|
||||
|
||||
#[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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user