rollup merge of #21897: dotdash/rposition

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)
````
This commit is contained in:
Alex Crichton 2015-02-03 15:36:04 -08:00
commit 1d921f557d

View File

@ -724,11 +724,12 @@ pub trait IteratorExt: Iterator + Sized {
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
}