Skip to content

Commit 175dd84

Browse files
authored
Rollup merge of rust-lang#47333 - arthurprs:iter-position-bounds-check, r=dtolnay
Optimize slice.{r}position result bounds check Second attempt of rust-lang#45501 Fixes rust-lang#45964 Demo: https://godbolt.org/g/N4mBHp
2 parents 283ee54 + 0b56ab0 commit 175dd84

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
@@ -1237,6 +1237,43 @@ macro_rules! iterator {
12371237
}
12381238
accum
12391239
}
1240+
1241+
#[inline]
1242+
#[rustc_inherit_overflow_checks]
1243+
fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
1244+
Self: Sized,
1245+
P: FnMut(Self::Item) -> bool,
1246+
{
1247+
// The addition might panic on overflow
1248+
let n = self.len();
1249+
self.try_fold(0, move |i, x| {
1250+
if predicate(x) { Err(i) }
1251+
else { Ok(i + 1) }
1252+
}).err()
1253+
.map(|i| {
1254+
unsafe { assume(i < n) };
1255+
i
1256+
})
1257+
}
1258+
1259+
#[inline]
1260+
fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
1261+
P: FnMut(Self::Item) -> bool,
1262+
Self: Sized + ExactSizeIterator + DoubleEndedIterator
1263+
{
1264+
// No need for an overflow check here, because `ExactSizeIterator`
1265+
// implies that the number of elements fits into a `usize`.
1266+
let n = self.len();
1267+
self.try_rfold(n, move |i, x| {
1268+
let i = i - 1;
1269+
if predicate(x) { Err(i) }
1270+
else { Ok(i) }
1271+
}).err()
1272+
.map(|i| {
1273+
unsafe { assume(i < n) };
1274+
i
1275+
})
1276+
}
12401277
}
12411278

12421279
#[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)