From ac8fb03a9050372ae868c849d015776b080c89ff Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 23 May 2024 19:23:03 +0000 Subject: [PATCH] manually outline closure this avoids capturing unused generic parameters, slightly improving compile times. The performance cost is a lot higher with the next-generation trait solver which pretty much hangs without this change. --- src/adaptors/mod.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index 52e36c48b..6f5e0260e 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -773,16 +773,28 @@ macro_rules! impl_tuple_combination { where F: FnMut(B, Self::Item) -> B, { + // We outline this closure to prevent it from unnecessarily + // capturing the type parameters `I`, `B`, and `F`. Not doing + // so ended up causing exponentially big types during MIR + // inlining when building itertools with optimizations enabled. + // + // This change causes a small improvement to compile times in + // release mode. + type CurrTuple = (A, $(ignore_ident!($X, A)),*); + type PrevTuple = ($(ignore_ident!($X, A),)*); + fn map_fn(z: &A) -> impl FnMut(PrevTuple) -> CurrTuple + '_ { + move |($($X,)*)| (z.clone(), $($X),*) + } let Self { c, item, mut iter } = self; if let Some(z) = item.as_ref() { init = c - .map(|($($X,)*)| (z.clone(), $($X),*)) + .map(map_fn::(z)) .fold(init, &mut f); } while let Some(z) = iter.next() { let c: $P = iter.clone().into(); init = c - .map(|($($X,)*)| (z.clone(), $($X),*)) + .map(map_fn::(&z)) .fold(init, &mut f); } init