Reduce the genericity of Map folds
This commit is contained in:
parent
755c091b71
commit
0e300e4380
2 changed files with 59 additions and 12 deletions
|
|
@ -594,6 +594,20 @@ impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
|
|||
}
|
||||
}
|
||||
|
||||
fn map_fold<T, B, Acc>(
|
||||
mut f: impl FnMut(T) -> B,
|
||||
mut g: impl FnMut(Acc, B) -> Acc,
|
||||
) -> impl FnMut(Acc, T) -> Acc {
|
||||
move |acc, elt| g(acc, f(elt))
|
||||
}
|
||||
|
||||
fn map_try_fold<'a, T, B, Acc, R>(
|
||||
f: &'a mut impl FnMut(T) -> B,
|
||||
mut g: impl FnMut(Acc, B) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
move |acc, elt| g(acc, f(elt))
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
|
||||
type Item = B;
|
||||
|
|
@ -608,18 +622,16 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
|
|||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
fn try_fold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
|
||||
fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
|
||||
Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
|
||||
{
|
||||
let f = &mut self.f;
|
||||
self.iter.try_fold(init, move |acc, elt| g(acc, f(elt)))
|
||||
self.iter.try_fold(init, map_try_fold(&mut self.f, g))
|
||||
}
|
||||
|
||||
fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc
|
||||
fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
|
||||
where G: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let mut f = self.f;
|
||||
self.iter.fold(init, move |acc, elt| g(acc, f(elt)))
|
||||
self.iter.fold(init, map_fold(self.f, g))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -632,18 +644,16 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where
|
|||
self.iter.next_back().map(&mut self.f)
|
||||
}
|
||||
|
||||
fn try_rfold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
|
||||
fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
|
||||
Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
|
||||
{
|
||||
let f = &mut self.f;
|
||||
self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt)))
|
||||
self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
|
||||
}
|
||||
|
||||
fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc
|
||||
fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
|
||||
where G: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let mut f = self.f;
|
||||
self.iter.rfold(init, move |acc, elt| g(acc, f(elt)))
|
||||
self.iter.rfold(init, map_fold(self.f, g))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
37
src/test/run-pass/iter-map-fold-type-length.rs
Normal file
37
src/test/run-pass/iter-map-fold-type-length.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//! Check that type lengths don't explode with `Map` folds.
|
||||
//!
|
||||
//! The normal limit is a million, and this test used to exceed 1.5 million, but
|
||||
//! now we can survive an even tighter limit. Still seems excessive though...
|
||||
#![type_length_limit = "256000"]
|
||||
|
||||
// Custom wrapper so Iterator methods aren't specialized.
|
||||
struct Iter<I>(I);
|
||||
|
||||
impl<I> Iterator for Iter<I>
|
||||
where
|
||||
I: Iterator
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let c = Iter(0i32..10)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.map(|x| x)
|
||||
.count();
|
||||
assert_eq!(c, 10);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue