The extra check caused by the expect() call can, in general, not be
optimized away, because the length of the iterator is unknown at compile
time, causing a noticable slow-down. Since the check only triggers if
the element isn't actually found in the iterator, i.e. it isn't
guaranteed to trigger for ill-behaved ExactSizeIterators, it seems
reasonable to switch to an implementation that doesn't need the check
and just always returns None if the value isn't found.
Benchmark:
````rust
let v: Vec<u8> = (0..1024*65).map(|_| 0).collect();
b.iter(|| {
v.as_slice().iter().rposition(|&c| c == 1)
});
````
Before:
````
test rposition ... bench: 49939 ns/iter (+/- 23)
````
After:
````
test rposition ... bench: 33306 ns/iter (+/- 68)
````
P: FnMut(Self::Item) -> bool,
Self: ExactSizeIterator + DoubleEndedIterator
{
- let len = self.len();
- for i in (0..len).rev() {
- if predicate(self.next_back().expect("rposition: incorrect ExactSizeIterator")) {
+ let mut i = self.len() - 1;
+ while let Some(v) = self.next_back() {
+ if predicate(v) {
return Some(i);
}
+ i -= 1;
}
None
}