Skip to content

Commit 6d0f160

Browse files
committed
Auto merge of #138835 - joboet:fold-via-try_fold, r=<try>
core: implement `fold` via `try_fold` ... and `rfold` via `try_rfold`. It's not possible to implement `try_fold` via `fold`, so this cannot lead to recursion. While unfortunately `try_fold` cannot be currently implemented for user types on stable, this paves a path to a future where implementing a good `try_fold` is enough to make nearly all `Iterator` traversal methods perform optimally. r? libs-api
2 parents 0ce1369 + 2ce188a commit 6d0f160

File tree

3 files changed

+6
-24
lines changed

3 files changed

+6
-24
lines changed

library/alloc/src/collections/vec_deque/into_iter.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,6 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
114114
.try_fold(init, &mut f)
115115
}
116116

117-
#[inline]
118-
fn fold<B, F>(mut self, init: B, mut f: F) -> B
119-
where
120-
F: FnMut(B, Self::Item) -> B,
121-
{
122-
match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
123-
Ok(b) => b,
124-
}
125-
}
126-
127117
#[inline]
128118
fn last(mut self) -> Option<Self::Item> {
129119
self.inner.pop_back()

library/core/src/iter/traits/double_ended.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::num::NonZero;
2-
use crate::ops::{ControlFlow, Try};
2+
use crate::ops::{ControlFlow, NeverShortCircuit, Try};
33

44
/// An iterator able to yield elements from both ends.
55
///
@@ -298,16 +298,12 @@ pub trait DoubleEndedIterator: Iterator {
298298
#[doc(alias = "foldr")]
299299
#[inline]
300300
#[stable(feature = "iter_rfold", since = "1.27.0")]
301-
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
301+
fn rfold<B, F>(mut self, init: B, f: F) -> B
302302
where
303303
Self: Sized,
304304
F: FnMut(B, Self::Item) -> B,
305305
{
306-
let mut accum = init;
307-
while let Some(x) = self.next_back() {
308-
accum = f(accum, x);
309-
}
310-
accum
306+
self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
311307
}
312308

313309
/// Searches for an element of an iterator from the back that satisfies a predicate.

library/core/src/iter/traits/iterator.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::super::{
77
use crate::array;
88
use crate::cmp::{self, Ordering};
99
use crate::num::NonZero;
10-
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
10+
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try};
1111

1212
fn _assert_is_dyn_compatible(_: &dyn Iterator<Item = ()>) {}
1313

@@ -2550,16 +2550,12 @@ pub trait Iterator {
25502550
#[doc(alias = "inject", alias = "foldl")]
25512551
#[inline]
25522552
#[stable(feature = "rust1", since = "1.0.0")]
2553-
fn fold<B, F>(mut self, init: B, mut f: F) -> B
2553+
fn fold<B, F>(mut self, init: B, f: F) -> B
25542554
where
25552555
Self: Sized,
25562556
F: FnMut(B, Self::Item) -> B,
25572557
{
2558-
let mut accum = init;
2559-
while let Some(x) = self.next() {
2560-
accum = f(accum, x);
2561-
}
2562-
accum
2558+
self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
25632559
}
25642560

25652561
/// Reduces the elements to a single one, by repeatedly applying a reducing

0 commit comments

Comments
 (0)