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
This commit is contained in:
commit
eb088b8b9d
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user