Skip to content

Commit 0b56ab0

Browse files
committed
Optimize slice.{r}position result bounds check
1 parent f62f774 commit 0b56ab0

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

src/libcore/slice/mod.rs

+37
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,43 @@ macro_rules! iterator {
12151215
}
12161216
accum
12171217
}
1218+
1219+
#[inline]
1220+
#[rustc_inherit_overflow_checks]
1221+
fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
1222+
Self: Sized,
1223+
P: FnMut(Self::Item) -> bool,
1224+
{
1225+
// The addition might panic on overflow
1226+
let n = self.len();
1227+
self.try_fold(0, move |i, x| {
1228+
if predicate(x) { Err(i) }
1229+
else { Ok(i + 1) }
1230+
}).err()
1231+
.map(|i| {
1232+
unsafe { assume(i < n) };
1233+
i
1234+
})
1235+
}
1236+
1237+
#[inline]
1238+
fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
1239+
P: FnMut(Self::Item) -> bool,
1240+
Self: Sized + ExactSizeIterator + DoubleEndedIterator
1241+
{
1242+
// No need for an overflow check here, because `ExactSizeIterator`
1243+
// implies that the number of elements fits into a `usize`.
1244+
let n = self.len();
1245+
self.try_rfold(n, move |i, x| {
1246+
let i = i - 1;
1247+
if predicate(x) { Err(i) }
1248+
else { Ok(i) }
1249+
}).err()
1250+
.map(|i| {
1251+
unsafe { assume(i < n) };
1252+
i
1253+
})
1254+
}
12181255
}
12191256

12201257
#[stable(feature = "rust1", since = "1.0.0")]

src/libcore/tests/slice.rs

+19
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,25 @@
1010

1111
use core::result::Result::{Ok, Err};
1212

13+
14+
#[test]
15+
fn test_position() {
16+
let b = [1, 2, 3, 5, 5];
17+
assert!(b.iter().position(|&v| v == 9) == None);
18+
assert!(b.iter().position(|&v| v == 5) == Some(3));
19+
assert!(b.iter().position(|&v| v == 3) == Some(2));
20+
assert!(b.iter().position(|&v| v == 0) == None);
21+
}
22+
23+
#[test]
24+
fn test_rposition() {
25+
let b = [1, 2, 3, 5, 5];
26+
assert!(b.iter().rposition(|&v| v == 9) == None);
27+
assert!(b.iter().rposition(|&v| v == 5) == Some(4));
28+
assert!(b.iter().rposition(|&v| v == 3) == Some(2));
29+
assert!(b.iter().rposition(|&v| v == 0) == None);
30+
}
31+
1332
#[test]
1433
fn test_binary_search() {
1534
let b: [i32; 0] = [];

0 commit comments

Comments
 (0)