Skip to content

Commit 2e82d11

Browse files
committed
Rollup merge of rust-lang#58730 - timvermeulen:internal_iteration, r=scottmcm
Have all methods of Filter and FilterMap use internal iteration This PR changes `Filter::{next, next_back, count}` and `FilterMap::{next, next_back}` to all use internal iteration. The `next` and `next_back` methods are changed to directly forward to `try_for_each` and `try_rfold` respectively, using `Result` as the `Try` type. I think that's okay? Alternatively, I could change their implementations to use `LoopState` instead if there's any benefit in doing so. r? @scottmcm
2 parents d987b46 + 88bd624 commit 2e82d11

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

src/libcore/benches/iter.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,13 @@ bench_sums! {
185185
bench_sums! {
186186
bench_filter_sum,
187187
bench_filter_ref_sum,
188-
(0i64..1000000).filter(|x| x % 2 == 0)
188+
(0i64..1000000).filter(|x| x % 3 == 0)
189189
}
190190

191191
bench_sums! {
192192
bench_filter_chain_sum,
193193
bench_filter_chain_ref_sum,
194-
(0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
194+
(0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
195195
}
196196

197197
bench_sums! {
@@ -306,3 +306,31 @@ fn bench_skip_then_zip(b: &mut Bencher) {
306306
assert_eq!(s, 2009900);
307307
});
308308
}
309+
310+
#[bench]
311+
fn bench_filter_count(b: &mut Bencher) {
312+
b.iter(|| {
313+
(0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
314+
})
315+
}
316+
317+
#[bench]
318+
fn bench_filter_ref_count(b: &mut Bencher) {
319+
b.iter(|| {
320+
(0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
321+
})
322+
}
323+
324+
#[bench]
325+
fn bench_filter_chain_count(b: &mut Bencher) {
326+
b.iter(|| {
327+
(0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
328+
})
329+
}
330+
331+
#[bench]
332+
fn bench_filter_chain_ref_count(b: &mut Bencher) {
333+
b.iter(|| {
334+
(0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
335+
})
336+
}

src/libcore/iter/adapters/mod.rs

+7-30
Original file line numberDiff line numberDiff line change
@@ -681,12 +681,7 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
681681

682682
#[inline]
683683
fn next(&mut self) -> Option<I::Item> {
684-
for x in &mut self.iter {
685-
if (self.predicate)(&x) {
686-
return Some(x);
687-
}
688-
}
689-
None
684+
self.try_for_each(Err).err()
690685
}
691686

692687
#[inline]
@@ -707,12 +702,9 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
707702
// Using the branchless version will also simplify the LLVM byte code, thus
708703
// leaving more budget for LLVM optimizations.
709704
#[inline]
710-
fn count(mut self) -> usize {
711-
let mut count = 0;
712-
for x in &mut self.iter {
713-
count += (self.predicate)(&x) as usize;
714-
}
715-
count
705+
fn count(self) -> usize {
706+
let mut predicate = self.predicate;
707+
self.iter.map(|x| predicate(&x) as usize).sum()
716708
}
717709

718710
#[inline]
@@ -746,12 +738,7 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
746738
{
747739
#[inline]
748740
fn next_back(&mut self) -> Option<I::Item> {
749-
for x in self.iter.by_ref().rev() {
750-
if (self.predicate)(&x) {
751-
return Some(x);
752-
}
753-
}
754-
None
741+
self.try_rfold((), |_, x| Err(x)).err()
755742
}
756743

757744
#[inline]
@@ -820,12 +807,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
820807

821808
#[inline]
822809
fn next(&mut self) -> Option<B> {
823-
for x in self.iter.by_ref() {
824-
if let Some(y) = (self.f)(x) {
825-
return Some(y);
826-
}
827-
}
828-
None
810+
self.try_for_each(Err).err()
829811
}
830812

831813
#[inline]
@@ -863,12 +845,7 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
863845
{
864846
#[inline]
865847
fn next_back(&mut self) -> Option<B> {
866-
for x in self.iter.by_ref().rev() {
867-
if let Some(y) = (self.f)(x) {
868-
return Some(y);
869-
}
870-
}
871-
None
848+
self.try_rfold((), |_, x| Err(x)).err()
872849
}
873850

874851
#[inline]

0 commit comments

Comments
 (0)