Skip to content

Commit 922cd41

Browse files
committed
Optimize Iterator implementation for &mut impl Iterator + Sized
1 parent 6f8c055 commit 922cd41

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

Diff for: library/core/src/iter/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,12 @@ macro_rules! impl_fold_via_try_fold {
361361
(rfold -> try_rfold) => {
362362
impl_fold_via_try_fold! { @internal rfold -> try_rfold }
363363
};
364+
(spec_fold -> spec_try_fold) => {
365+
impl_fold_via_try_fold! { @internal spec_fold -> spec_try_fold }
366+
};
367+
(spec_rfold -> spec_try_rfold) => {
368+
impl_fold_via_try_fold! { @internal spec_rfold -> spec_try_rfold }
369+
};
364370
(@internal $fold:ident -> $try_fold:ident) => {
365371
#[inline]
366372
fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA

Diff for: library/core/src/iter/traits/double_ended.rs

+62
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,66 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
379379
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
380380
(**self).nth_back(n)
381381
}
382+
fn rfold<B, F>(self, init: B, f: F) -> B
383+
where
384+
F: FnMut(B, Self::Item) -> B,
385+
{
386+
self.spec_rfold(init, f)
387+
}
388+
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
389+
where
390+
F: FnMut(B, Self::Item) -> R,
391+
R: Try<Output = B>,
392+
{
393+
self.spec_try_rfold(init, f)
394+
}
395+
}
396+
397+
/// Helper trait to specialize `rfold` and `rtry_fold` for `&mut I where I: Sized`
398+
trait DoubleEndedIteratorRefSpec: DoubleEndedIterator {
399+
fn spec_rfold<B, F>(self, init: B, f: F) -> B
400+
where
401+
F: FnMut(B, Self::Item) -> B;
402+
403+
fn spec_try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
404+
where
405+
F: FnMut(B, Self::Item) -> R,
406+
R: Try<Output = B>;
407+
}
408+
409+
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIteratorRefSpec for &mut I {
410+
default fn spec_rfold<B, F>(self, init: B, mut f: F) -> B
411+
where
412+
F: FnMut(B, Self::Item) -> B,
413+
{
414+
let mut accum = init;
415+
while let Some(x) = self.next_back() {
416+
accum = f(accum, x);
417+
}
418+
accum
419+
}
420+
421+
default fn spec_try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
422+
where
423+
F: FnMut(B, Self::Item) -> R,
424+
R: Try<Output = B>,
425+
{
426+
let mut accum = init;
427+
while let Some(x) = self.next_back() {
428+
accum = f(accum, x)?;
429+
}
430+
try { accum }
431+
}
432+
}
433+
434+
impl<I: DoubleEndedIterator> DoubleEndedIteratorRefSpec for &mut I {
435+
impl_fold_via_try_fold! { spec_rfold -> spec_try_rfold }
436+
437+
fn spec_try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
438+
where
439+
F: FnMut(B, Self::Item) -> R,
440+
R: Try<Output = B>,
441+
{
442+
(**self).try_rfold(init, f)
443+
}
382444
}

Diff for: library/core/src/iter/traits/iterator.rs

+62
Original file line numberDiff line numberDiff line change
@@ -4018,4 +4018,66 @@ impl<I: Iterator + ?Sized> Iterator for &mut I {
40184018
fn nth(&mut self, n: usize) -> Option<Self::Item> {
40194019
(**self).nth(n)
40204020
}
4021+
fn fold<B, F>(self, init: B, f: F) -> B
4022+
where
4023+
F: FnMut(B, Self::Item) -> B,
4024+
{
4025+
self.spec_fold(init, f)
4026+
}
4027+
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
4028+
where
4029+
F: FnMut(B, Self::Item) -> R,
4030+
R: Try<Output = B>,
4031+
{
4032+
self.spec_try_fold(init, f)
4033+
}
4034+
}
4035+
4036+
/// Helper trait to specialize `fold` and `try_fold` for `&mut I where I: Sized`
4037+
trait IteratorRefSpec: Iterator {
4038+
fn spec_fold<B, F>(self, init: B, f: F) -> B
4039+
where
4040+
F: FnMut(B, Self::Item) -> B;
4041+
4042+
fn spec_try_fold<B, F, R>(&mut self, init: B, f: F) -> R
4043+
where
4044+
F: FnMut(B, Self::Item) -> R,
4045+
R: Try<Output = B>;
4046+
}
4047+
4048+
impl<I: Iterator + ?Sized> IteratorRefSpec for &mut I {
4049+
default fn spec_fold<B, F>(self, init: B, mut f: F) -> B
4050+
where
4051+
F: FnMut(B, Self::Item) -> B,
4052+
{
4053+
let mut accum = init;
4054+
while let Some(x) = self.next() {
4055+
accum = f(accum, x);
4056+
}
4057+
accum
4058+
}
4059+
4060+
default fn spec_try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
4061+
where
4062+
F: FnMut(B, Self::Item) -> R,
4063+
R: Try<Output = B>,
4064+
{
4065+
let mut accum = init;
4066+
while let Some(x) = self.next() {
4067+
accum = f(accum, x)?;
4068+
}
4069+
try { accum }
4070+
}
4071+
}
4072+
4073+
impl<I: Iterator> IteratorRefSpec for &mut I {
4074+
impl_fold_via_try_fold! { spec_fold -> spec_try_fold }
4075+
4076+
fn spec_try_fold<B, F, R>(&mut self, init: B, f: F) -> R
4077+
where
4078+
F: FnMut(B, Self::Item) -> R,
4079+
R: Try<Output = B>,
4080+
{
4081+
(**self).try_fold(init, f)
4082+
}
40214083
}

0 commit comments

Comments
 (0)