Skip to content

Commit

Permalink
Auto merge of #47180 - varkor:range-iterator-overrides, r=alexcrichton
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Jan 8, 2018
2 parents b5392f5 + 2d83343 commit 2248d5b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/libcore/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@ impl<A: Step> Iterator for ops::Range<A> {
self.start = self.end.clone();
None
}

#[inline]
fn max(mut self) -> Option<A> {
self.next_back()
}
}

// These macros generate `ExactSizeIterator` impls for various range types.
Expand Down Expand Up @@ -367,6 +372,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")]
Expand Down
34 changes: 34 additions & 0 deletions src/libcore/tests/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,40 @@ 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_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_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);
Expand Down

0 comments on commit 2248d5b

Please sign in to comment.