Skip to content

Commit e67620a

Browse files
committed
Reduce the genericity of closures in the iterator traits
By default, closures inherit the generic parameters of their scope, including `Self`. However, in most cases, the closures used to implement iterators don't need to be generic on the iterator type, only its `Item` type. We can reduce this genericity by redirecting such closures through local functions. This does make the closures more cumbersome to write, but it will hopefully reduce duplication in their monomorphizations, as well as their related type lengths.
1 parent 60960a2 commit e67620a

File tree

3 files changed

+194
-80
lines changed

3 files changed

+194
-80
lines changed

src/libcore/iter/traits/accum.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,28 +85,28 @@ macro_rules! float_sum_product {
8585
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
8686
impl Sum for $a {
8787
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
88-
iter.fold(0.0, |a, b| a + b)
88+
iter.fold(0.0, Add::add)
8989
}
9090
}
9191

9292
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
9393
impl Product for $a {
9494
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
95-
iter.fold(1.0, |a, b| a * b)
95+
iter.fold(1.0, Mul::mul)
9696
}
9797
}
9898

9999
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
100100
impl<'a> Sum<&'a $a> for $a {
101101
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
102-
iter.fold(0.0, |a, b| a + *b)
102+
iter.fold(0.0, Add::add)
103103
}
104104
}
105105

106106
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
107107
impl<'a> Product<&'a $a> for $a {
108108
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
109-
iter.fold(1.0, |a, b| a * *b)
109+
iter.fold(1.0, Mul::mul)
110110
}
111111
}
112112
)*)

src/libcore/iter/traits/double_ended.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,17 @@ pub trait DoubleEndedIterator: Iterator {
219219
/// ```
220220
#[inline]
221221
#[stable(feature = "iter_rfold", since = "1.27.0")]
222-
fn rfold<B, F>(mut self, accum: B, mut f: F) -> B
222+
fn rfold<B, F>(mut self, accum: B, f: F) -> B
223223
where
224224
Self: Sized,
225225
F: FnMut(B, Self::Item) -> B,
226226
{
227-
self.try_rfold(accum, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
227+
#[inline]
228+
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
229+
move |acc, x| Ok(f(acc, x))
230+
}
231+
232+
self.try_rfold(accum, ok(f)).unwrap()
228233
}
229234

230235
/// Searches for an element of an iterator from the back that satisfies a predicate.
@@ -271,15 +276,21 @@ pub trait DoubleEndedIterator: Iterator {
271276
/// ```
272277
#[inline]
273278
#[stable(feature = "iter_rfind", since = "1.27.0")]
274-
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
279+
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
275280
where
276281
Self: Sized,
277282
P: FnMut(&Self::Item) -> bool
278283
{
279-
self.try_rfold((), move |(), x| {
280-
if predicate(&x) { LoopState::Break(x) }
281-
else { LoopState::Continue(()) }
282-
}).break_value()
284+
#[inline]
285+
fn check<T>(
286+
mut predicate: impl FnMut(&T) -> bool,
287+
) -> impl FnMut((), T) -> LoopState<(), T> {
288+
move |(), x| {
289+
if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
290+
}
291+
}
292+
293+
self.try_rfold((), check(predicate)).break_value()
283294
}
284295
}
285296

0 commit comments

Comments
 (0)