Skip to content

Commit 0e300e4

Browse files
committed
Reduce the genericity of Map folds
1 parent 755c091 commit 0e300e4

File tree

2 files changed

+59
-12
lines changed

2 files changed

+59
-12
lines changed

src/libcore/iter/adapters/mod.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,20 @@ impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
594594
}
595595
}
596596

597+
fn map_fold<T, B, Acc>(
598+
mut f: impl FnMut(T) -> B,
599+
mut g: impl FnMut(Acc, B) -> Acc,
600+
) -> impl FnMut(Acc, T) -> Acc {
601+
move |acc, elt| g(acc, f(elt))
602+
}
603+
604+
fn map_try_fold<'a, T, B, Acc, R>(
605+
f: &'a mut impl FnMut(T) -> B,
606+
mut g: impl FnMut(Acc, B) -> R + 'a,
607+
) -> impl FnMut(Acc, T) -> R + 'a {
608+
move |acc, elt| g(acc, f(elt))
609+
}
610+
597611
#[stable(feature = "rust1", since = "1.0.0")]
598612
impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
599613
type Item = B;
@@ -608,18 +622,16 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B {
608622
self.iter.size_hint()
609623
}
610624

611-
fn try_fold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
625+
fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
612626
Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
613627
{
614-
let f = &mut self.f;
615-
self.iter.try_fold(init, move |acc, elt| g(acc, f(elt)))
628+
self.iter.try_fold(init, map_try_fold(&mut self.f, g))
616629
}
617630

618-
fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc
631+
fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
619632
where G: FnMut(Acc, Self::Item) -> Acc,
620633
{
621-
let mut f = self.f;
622-
self.iter.fold(init, move |acc, elt| g(acc, f(elt)))
634+
self.iter.fold(init, map_fold(self.f, g))
623635
}
624636
}
625637

@@ -632,18 +644,16 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where
632644
self.iter.next_back().map(&mut self.f)
633645
}
634646

635-
fn try_rfold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where
647+
fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where
636648
Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
637649
{
638-
let f = &mut self.f;
639-
self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt)))
650+
self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
640651
}
641652

642-
fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc
653+
fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
643654
where G: FnMut(Acc, Self::Item) -> Acc,
644655
{
645-
let mut f = self.f;
646-
self.iter.rfold(init, move |acc, elt| g(acc, f(elt)))
656+
self.iter.rfold(init, map_fold(self.f, g))
647657
}
648658
}
649659

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! Check that type lengths don't explode with `Map` folds.
2+
//!
3+
//! The normal limit is a million, and this test used to exceed 1.5 million, but
4+
//! now we can survive an even tighter limit. Still seems excessive though...
5+
#![type_length_limit = "256000"]
6+
7+
// Custom wrapper so Iterator methods aren't specialized.
8+
struct Iter<I>(I);
9+
10+
impl<I> Iterator for Iter<I>
11+
where
12+
I: Iterator
13+
{
14+
type Item = I::Item;
15+
16+
fn next(&mut self) -> Option<Self::Item> {
17+
self.0.next()
18+
}
19+
}
20+
21+
fn main() {
22+
let c = Iter(0i32..10)
23+
.map(|x| x)
24+
.map(|x| x)
25+
.map(|x| x)
26+
.map(|x| x)
27+
.map(|x| x)
28+
.map(|x| x)
29+
.map(|x| x)
30+
.map(|x| x)
31+
.map(|x| x)
32+
.map(|x| x)
33+
.map(|x| x)
34+
.map(|x| x)
35+
.count();
36+
assert_eq!(c, 10);
37+
}

0 commit comments

Comments
 (0)