diff options
| author | bors <bors@rust-lang.org> | 2023-08-05 17:38:26 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-08-05 17:38:26 +0000 |
| commit | eb088b8b9d98f1af1b0e61bbdcd8686e1b0db7b6 (patch) | |
| tree | f3a57a58f2cb31229d56029d77e6418eea30dd3c | |
| parent | 9565b68b741fd0466b3af075139e819e7d73ee38 (diff) | |
| parent | 922cd417ea6f5eed76842b89abf4106e33e00cc0 (diff) | |
| download | rust-eb088b8b9d98f1af1b0e61bbdcd8686e1b0db7b6.tar.gz rust-eb088b8b9d98f1af1b0e61bbdcd8686e1b0db7b6.zip | |
Auto merge of #111200 - a1phyr:spec_sized_iterators, r=the8472
Optimize `Iterator` implementation for `&mut impl Iterator + Sized` This adds a specialization trait to forward `fold`, `try_fold`,... to the inner iterator where possible
| -rw-r--r-- | library/core/src/iter/mod.rs | 6 | ||||
| -rw-r--r-- | library/core/src/iter/traits/double_ended.rs | 62 | ||||
| -rw-r--r-- | library/core/src/iter/traits/iterator.rs | 62 |
3 files changed, 130 insertions, 0 deletions
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index de638552fa3..be04dfe042e 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<AAA, FFF>(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 182d9f758ad..4c8af4eba78 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<I::Item> { (**self).nth_back(n) } + fn rfold<B, F>(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.spec_rfold(init, f) + } + fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + 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<B, F>(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B; + + fn spec_try_rfold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>; +} + +impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIteratorRefSpec for &mut I { + default fn spec_rfold<B, F>(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<B, F, R>(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + let mut accum = init; + while let Some(x) = self.next_back() { + accum = f(accum, x)?; + } + try { accum } + } +} + +impl<I: DoubleEndedIterator> DoubleEndedIteratorRefSpec for &mut I { + impl_fold_via_try_fold! { spec_rfold -> spec_try_rfold } + + fn spec_try_rfold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + (**self).try_rfold(init, f) + } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 98835228308..cecc120a6e2 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4018,4 +4018,66 @@ impl<I: Iterator + ?Sized> Iterator for &mut I { fn nth(&mut self, n: usize) -> Option<Self::Item> { (**self).nth(n) } + fn fold<B, F>(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.spec_fold(init, f) + } + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + 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<B, F>(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B; + + fn spec_try_fold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>; +} + +impl<I: Iterator + ?Sized> IteratorRefSpec for &mut I { + default fn spec_fold<B, F>(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<B, F, R>(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x)?; + } + try { accum } + } +} + +impl<I: Iterator> IteratorRefSpec for &mut I { + impl_fold_via_try_fold! { spec_fold -> spec_try_fold } + + fn spec_try_fold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + (**self).try_fold(init, f) + } } |
