From 922cd417ea6f5eed76842b89abf4106e33e00cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Thu, 4 May 2023 14:48:03 +0200 Subject: [PATCH] Optimize `Iterator` implementation for `&mut impl Iterator + Sized` --- library/core/src/iter/mod.rs | 6 ++ library/core/src/iter/traits/double_ended.rs | 62 ++++++++++++++++++++ library/core/src/iter/traits/iterator.rs | 62 ++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index de638552fa378..be04dfe042e9f 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -361,6 +361,12 @@ macro_rules! impl_fold_via_try_fold { (rfold -> try_rfold) => { impl_fold_via_try_fold! { @internal rfold -> try_rfold } }; + (spec_fold -> spec_try_fold) => { + impl_fold_via_try_fold! { @internal spec_fold -> spec_try_fold } + }; + (spec_rfold -> spec_try_rfold) => { + impl_fold_via_try_fold! { @internal spec_rfold -> spec_try_rfold } + }; (@internal $fold:ident -> $try_fold:ident) => { #[inline] fn $fold(mut self, init: AAA, fold: FFF) -> AAA diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 182d9f758adc4..4c8af4eba7889 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -379,4 +379,66 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { fn nth_back(&mut self, n: usize) -> Option { (**self).nth_back(n) } + fn rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.spec_rfold(init, f) + } + fn try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_rfold(init, f) + } +} + +/// Helper trait to specialize `rfold` and `rtry_fold` for `&mut I where I: Sized` +trait DoubleEndedIteratorRefSpec: DoubleEndedIterator { + fn spec_rfold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B; + + fn spec_try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl DoubleEndedIteratorRefSpec for &mut I { + default fn spec_rfold(self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x); + } + accum + } + + default fn spec_try_rfold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + try { accum } + } +} + +impl DoubleEndedIteratorRefSpec for &mut I { + impl_fold_via_try_fold! { spec_rfold -> spec_try_rfold } + + fn spec_try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + (**self).try_rfold(init, f) + } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index dabfce1447483..f8ca75a868d3f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4018,4 +4018,66 @@ impl Iterator for &mut I { fn nth(&mut self, n: usize) -> Option { (**self).nth(n) } + fn fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.spec_fold(init, f) + } + fn try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.spec_try_fold(init, f) + } +} + +/// Helper trait to specialize `fold` and `try_fold` for `&mut I where I: Sized` +trait IteratorRefSpec: Iterator { + fn spec_fold(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B; + + fn spec_try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl IteratorRefSpec for &mut I { + default fn spec_fold(self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x); + } + accum + } + + default fn spec_try_fold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + try { accum } + } +} + +impl IteratorRefSpec for &mut I { + impl_fold_via_try_fold! { spec_fold -> spec_try_fold } + + fn spec_try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + (**self).try_fold(init, f) + } }