[FIR] ~ Introduce `zipLet` function
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt
index 555d401..fa2f0b7 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt
@@ -29,6 +29,7 @@
 import org.jetbrains.kotlin.utils.SmartList
 import org.jetbrains.kotlin.utils.SmartSet
 import org.jetbrains.kotlin.utils.addIfNotNull
+import org.jetbrains.kotlin.utils.addToStdlib.zipToMap
 
 abstract class SupertypeSupplier {
     abstract fun forClass(firClass: FirClass, useSiteSession: FirSession): List<ConeClassLikeType>
@@ -308,7 +309,7 @@
     val arguments = superType.typeArguments.map {
         it as? ConeKotlinType ?: ConeErrorType(ConeSimpleDiagnostic("illegal projection usage", DiagnosticKind.IllegalProjectionUsage))
     }
-    val mapping = klass.typeParameters.map { it.symbol }.zip(arguments).toMap()
+    val mapping = klass.typeParameters.map { it.symbol }.zipToMap(arguments)
     return substitutorByMap(mapping, session)
 }
 
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt
index 53c7880..60b2ed7 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt
@@ -605,7 +605,7 @@
 
         val substitutor = if (declaration is FirTypeParameterRefsOwner) {
             val substitution =
-                declaration.typeParameters.zip(type.typeArguments).associate { (parameter, argument) ->
+                declaration.typeParameters. zip(type.typeArguments).associate { (parameter, argument) ->
                     parameter.symbol to ((argument as? ConeKotlinTypeProjection)?.type
                         ?: session.builtinTypes.nullableAnyType.coneType)//StandardClassIds.Any(session.firSymbolProvider).constructType(emptyArray(), isNullable = true))
                 }
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUnification.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUnification.kt
index cf32d9c..61b4b44 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUnification.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUnification.kt
@@ -10,6 +10,7 @@
 import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
 import org.jetbrains.kotlin.types.AbstractTypeChecker
 import org.jetbrains.kotlin.types.model.KotlinTypeMarker
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 /**
  * @return false does only mean that there were conflicted values for some type parameter. In all other cases, it returns true.
@@ -116,7 +117,7 @@
     }
 
     // Foo<...> ~ Foo<...>
-    for ((originalTypeArgument, typeWithParametersArgument) in originalType.typeArguments.zip(typeWithParameters.typeArguments)) {
+    originalType.typeArguments.zipLet(typeWithParameters.typeArguments) { originalTypeArgument, typeWithParametersArgument ->
         if (!doUnify(originalTypeArgument, typeWithParametersArgument, targetTypeParameters, result)) return false
     }
 
diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt
index a8427ed..bdaa7a3 100644
--- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt
+++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt
@@ -49,6 +49,7 @@
 import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
 import org.jetbrains.kotlin.utils.addToStdlib.runIf
 import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
 import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment
 import org.jetbrains.kotlin.utils.exceptions.withPsiEntry
@@ -1745,9 +1746,7 @@
                             val primaryConstructor = classOrObject.primaryConstructor
                             val firPrimaryConstructor = declarations.firstOrNull { it is FirConstructor } as? FirConstructor
                             if (primaryConstructor != null && firPrimaryConstructor != null) {
-                                primaryConstructor.valueParameters.zip(
-                                    firPrimaryConstructor.valueParameters
-                                ).forEach { (ktParameter, firParameter) ->
+                                primaryConstructor.valueParameters.zipLet(firPrimaryConstructor.valueParameters) { ktParameter, firParameter ->
                                     if (ktParameter.hasValOrVar()) {
                                         addDeclaration(ktParameter.toFirProperty(firParameter))
                                     }
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt
index ce1ccfd..e4cdae8 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt
@@ -48,6 +48,8 @@
 import org.jetbrains.kotlin.name.StandardClassIds
 import org.jetbrains.kotlin.types.Variance
 import org.jetbrains.kotlin.utils.addToStdlib.unreachableBranch
+import org.jetbrains.kotlin.utils.addToStdlib.zipToMap
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
 
 private val SAM_PARAMETER_NAME = Name.identifier("function")
@@ -162,11 +164,11 @@
         val substitutor = substitutorByMap(
             firRegularClass.typeParameters
                 .map { it.symbol }
-                .zip(newTypeParameterTypes).toMap(),
+                .zipToMap(newTypeParameterTypes),
             session
         )
 
-        for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(firRegularClass.typeParameters)) {
+        newTypeParameters.zipLet(firRegularClass.typeParameters) { newTypeParameter, oldTypeParameter ->
             val declared = oldTypeParameter.symbol.fir
             newTypeParameter.bounds += declared.symbol.resolvedBounds.map { typeRef ->
                 buildResolvedTypeRef {
@@ -305,25 +307,27 @@
     var containsNonSubstitutedArguments = false
 
     fun createMapping(substitutor: ConeSubstitutor): Map<FirTypeParameterSymbol, ConeKotlinType> {
-        return typeParameters.zip(type.typeArguments).associate { (parameter, projection) ->
-            val typeArgument =
-                projection.type?.let(substitutor::substituteOrSelf)
-                // TODO: Consider using `parameterSymbol.fir.bounds.first().coneType` once sure that it won't fail with exception
-                    ?: parameter.symbol.fir.bounds.firstOrNull()?.coneTypeOrNull
-                        ?.let(substitutor::substituteOrSelf)
-                        ?.also { bound ->
-                            // We only check for type parameters in upper bounds
-                            // because `projection` can contain a type parameter type as well in a situation like
-                            // fun interface Sam<T> {
-                            //      fun invoke()
-                            //      fun foo(s: Sam<T>) {} <--- here T is substituted with T but it's not a recursion
-                            // }
-                            if (bound.containsReferenceToOtherTypeParameter(this)) {
-                                containsNonSubstitutedArguments = true
+        return buildMap<FirTypeParameterSymbol, ConeKotlinType> {
+            typeParameters.zipLet(type.typeArguments) { parameter: FirTypeParameterRef, projection: ConeTypeProjection ->
+                val typeArgument =
+                    projection.type?.let(substitutor::substituteOrSelf)
+                    // TODO: Consider using `parameterSymbol.fir.bounds.first().coneType` once sure that it won't fail with exception
+                        ?: parameter.symbol.fir.bounds.firstOrNull()?.coneTypeOrNull
+                            ?.let(substitutor::substituteOrSelf)
+                            ?.also { bound ->
+                                // We only check for type parameters in upper bounds
+                                // because `projection` can contain a type parameter type as well in a situation like
+                                // fun interface Sam<T> {
+                                //      fun invoke()
+                                //      fun foo(s: Sam<T>) {} <--- here T is substituted with T but it's not a recursion
+                                // }
+                                if (bound.containsReferenceToOtherTypeParameter(this@buildSubstitutorWithUpperBounds)) {
+                                    containsNonSubstitutedArguments = true
+                                }
                             }
-                        }
-                    ?: session.builtinTypes.nullableAnyType.coneType
-            Pair(parameter.symbol, typeArgument)
+                        ?: session.builtinTypes.nullableAnyType.coneType
+                put(parameter.symbol, typeArgument)
+            }
         }
     }
 
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/CheckArguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/CheckArguments.kt
index 3d0b400..c69c4c5 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/CheckArguments.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/CheckArguments.kt
@@ -22,6 +22,7 @@
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.types.AbstractTypeChecker
 import org.jetbrains.kotlin.types.model.typeConstructor
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 internal object CheckArguments : ResolutionStage() {
     override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
@@ -235,22 +236,23 @@
     if (invokeSymbol.fir.valueParameters.size != classLikeExpectedFunctionType.typeArguments.size - 1) {
         return false
     }
-    val parameterPairs =
-        invokeSymbol.fir.valueParameters.zip(classLikeExpectedFunctionType.valueParameterTypesIncludingReceiver(session))
-    return parameterPairs.all { (invokeParameter, expectedParameter) ->
+
+    invokeSymbol.fir.valueParameters.zipLet(classLikeExpectedFunctionType.valueParameterTypesIncludingReceiver(session)) { invokeParameter, expectedParameter ->
         val expectedParameterType = expectedParameter.unwrapToSimpleTypeUsingLowerBound()
         // TODO: can we remove is ConeTypeParameterType check here?
-        expectedParameterType is ConeTypeParameterType ||
-                AbstractTypeChecker.isSubtypeOf(
-                    session.typeContext.newTypeCheckerState(
-                        errorTypesEqualToAnything = false,
-                        stubTypesEqualToAnything = true
-                    ),
-                    invokeParameter.returnTypeRef.coneType,
-                    expectedParameterType,
-                    isFromNullabilityConstraint = false
-                )
+        if (expectedParameterType !is ConeTypeParameterType &&
+            !AbstractTypeChecker.isSubtypeOf(
+                session.typeContext.newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true),
+                invokeParameter.returnTypeRef.coneType,
+                expectedParameterType,
+                isFromNullabilityConstraint = false
+            )
+        ) {
+            return false
+        }
     }
+
+    return true
 }
 
 private fun getExpectedTypeWithImplicitIntegerCoercion(
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt
index 21426d6..fe2a4e8 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt
@@ -41,6 +41,8 @@
 import org.jetbrains.kotlin.types.ConstantValueKind
 import org.jetbrains.kotlin.types.SmartcastStability
 import org.jetbrains.kotlin.util.OperatorNameConventions
+import org.jetbrains.kotlin.utils.addToStdlib.getOrPut
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 class DataFlowAnalyzerContext(private val session: FirSession) {
     val graphBuilder: ControlFlowGraphBuilder = ControlFlowGraphBuilder()
@@ -1035,10 +1037,13 @@
 
         val typeParameters = callee.typeParameters
         val typeArgumentsSubstitutor = if (typeParameters.isNotEmpty() && qualifiedAccess is FirQualifiedAccessExpression) {
-            @Suppress("UNCHECKED_CAST")
-            val substitutionFromArguments = typeParameters.zip(qualifiedAccess.typeArguments).map { (typeParameterRef, typeArgument) ->
-                typeParameterRef.symbol to typeArgument.toConeTypeProjection().type
-            }.filter { it.second != null }.toMap() as Map<FirTypeParameterSymbol, ConeKotlinType>
+            val substitutionFromArguments = buildMap<FirTypeParameterSymbol, ConeKotlinType> {
+                typeParameters.zipLet(qualifiedAccess.typeArguments) { typeParameterRef, typeArgument ->
+                    typeArgument.toConeTypeProjection().type?.let {
+                        put(typeParameterRef.symbol, it)
+                    }
+                }
+            }
             substitutorByMap(substitutionFromArguments, components.session)
         } else {
             ConeSubstitutor.Empty
@@ -1048,7 +1053,11 @@
         val substitutor = if (originalFunction == null) {
             typeArgumentsSubstitutor
         } else {
-            val map = originalFunction.symbol.typeParameterSymbols.zip(typeParameters.map { it.symbol.toConeType() }).toMap()
+            val map = buildMap {
+                originalFunction.symbol.typeParameterSymbols.zipLet(typeParameters) { typeParameterSymbol, typeParameter ->
+                    put(typeParameterSymbol, typeParameter.symbol.toConeType())
+                }
+            }
             substitutorByMap(map, components.session).chain(typeArgumentsSubstitutor)
         }
 
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
index 53aab07..8b5bd53 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt
@@ -67,6 +67,8 @@
 import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
 import org.jetbrains.kotlin.utils.addToStdlib.runIf
 import org.jetbrains.kotlin.utils.addToStdlib.runUnless
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
+import org.jetbrains.kotlin.utils.addToStdlib.zipToMap
 import kotlin.collections.component1
 import kotlin.collections.component2
 
@@ -255,8 +257,10 @@
         @OptIn(Candidate.UpdatingCandidateInvariants::class)
         updateSubstitutor(
             substitutorByMap(
-                updatedSymbol.typeParameterSymbols.zip(freshVariables).associate { (typeParameter, typeVariable) ->
-                    typeParameter to typeVariable.defaultType
+                buildMap {
+                    updatedSymbol.typeParameterSymbols.zipLet(freshVariables) { typeParameter, typeVariable ->
+                        put(typeParameter, typeVariable.defaultType)
+                    }
                 },
                 session,
             )
@@ -266,7 +270,7 @@
         require(oldSymbol is FirFunctionSymbol)
 
         val oldArgumentMapping = argumentMapping
-        val oldValueParametersToNewMap = oldSymbol.valueParameterSymbols.zip(updatedSymbol.valueParameterSymbols).toMap()
+        val oldValueParametersToNewMap = oldSymbol.valueParameterSymbols.zipToMap(updatedSymbol.valueParameterSymbols)
 
         @OptIn(Candidate.UpdatingCandidateInvariants::class)
         updateArgumentMapping(oldArgumentMapping.mapValuesTo(linkedMapOf()) { oldValueParametersToNewMap[it.value.symbol]!!.fir })
diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/expressions/SubstitutionUtils.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/expressions/SubstitutionUtils.kt
index 559c049..b390ff2 100644
--- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/expressions/SubstitutionUtils.kt
+++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/expressions/SubstitutionUtils.kt
@@ -13,6 +13,7 @@
 import org.jetbrains.kotlin.fir.types.ConeErrorType
 import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
 import org.jetbrains.kotlin.fir.types.coneType
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 fun FirQualifiedAccessExpression.createConeSubstitutorFromTypeArguments(
     session: FirSession,
@@ -36,9 +37,10 @@
         // Type arguments are ignored defensively if `callableSymbol` can't provide enough type parameters (and vice versa). For
         // example, when call candidates are collected, the candidate's `callableSymbol` might have fewer type parameters than the
         // inferred call's type arguments.
-        typeArguments.zip(callableSymbol.typeParameterSymbols).forEach { (typeArgument, typeParameterSymbol) ->
-            val type = (typeArgument as? FirTypeProjectionWithVariance)?.typeRef?.coneType ?: return@forEach
-            if (type is ConeErrorType && discardErrorTypes) return@forEach
+
+        typeArguments.zipLet(callableSymbol.typeParameterSymbols) { typeArgument, typeParameterSymbol ->
+            val type = (typeArgument as? FirTypeProjectionWithVariance)?.typeRef?.coneType ?: return@zipLet
+            if (type is ConeErrorType && discardErrorTypes) return@zipLet
 
             val resultingType = when {
                 unwrapExplicitTypeArgumentForMadeFlexibleSynthetically ->
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirCallableDeclarationComparator.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirCallableDeclarationComparator.kt
index 571f8d5..bc99ae4 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirCallableDeclarationComparator.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirCallableDeclarationComparator.kt
@@ -9,6 +9,7 @@
 import org.jetbrains.kotlin.fir.declarations.FirFunction
 import org.jetbrains.kotlin.fir.render
 import org.jetbrains.kotlin.fir.types.FirTypeRefComparator
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 object FirCallableDeclarationComparator : Comparator<FirCallableDeclaration> {
     override fun compare(a: FirCallableDeclaration, b: FirCallableDeclaration): Int {
@@ -45,7 +46,7 @@
             if (valueParameterSizeDiff != 0) {
                 return valueParameterSizeDiff
             }
-            for ((aValueParameter, bValueParameter) in a.valueParameters.zip(b.valueParameters)) {
+            a.valueParameters.zipLet(b.valueParameters) { aValueParameter, bValueParameter ->
                 val valueParameterDiff = FirValueParameterComparator.compare(aValueParameter, bValueParameter)
                 if (valueParameterDiff != 0) {
                     return valueParameterDiff
@@ -58,7 +59,8 @@
         if (typeParameterSizeDiff != 0) {
             return typeParameterSizeDiff
         }
-        for ((aTypeParameter, bTypeParameter) in a.typeParameters.zip(b.typeParameters)) {
+
+        a.typeParameters.zipLet(b.typeParameters) { aTypeParameter, bTypeParameter ->
             val typeParameterDiff = FirTypeParameterRefComparator.compare(aTypeParameter, bTypeParameter)
             if (typeParameterDiff != 0) {
                 return typeParameterDiff
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirTypeParameterRefComparator.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirTypeParameterRefComparator.kt
index 5f39c6c..aa89085 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirTypeParameterRefComparator.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/comparators/FirTypeParameterRefComparator.kt
@@ -11,6 +11,7 @@
 import org.jetbrains.kotlin.fir.declarations.FirOuterClassTypeParameterRef
 import org.jetbrains.kotlin.fir.render
 import org.jetbrains.kotlin.fir.types.FirTypeRefComparator
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 object FirTypeParameterRefComparator : Comparator<FirTypeParameterRef> {
     private val FirTypeParameterRef.priority : Int
@@ -55,12 +56,13 @@
                 if (boundsSizeDiff != 0) {
                     return boundsSizeDiff
                 }
-                for ((aBound, bBound) in a.bounds.zip(b.bounds)) {
+                a.bounds.zipLet(b.bounds) { aBound, bBound ->
                     val boundDiff = FirTypeRefComparator.compare(aBound, bBound)
                     if (boundDiff != 0) {
                         return boundDiff
                     }
                 }
+
                 return 0
             }
             else ->
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt
index a9ec028..5df190b 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt
@@ -25,6 +25,7 @@
 import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.types.ConstantValueKind
 import org.jetbrains.kotlin.utils.addIfNotNull
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 inline val FirAnnotation.unexpandedConeClassLikeType: ConeClassLikeType?
     get() = ((annotationTypeRef as? FirResolvedTypeRef)?.coneType as? ConeClassLikeType)
@@ -171,10 +172,9 @@
 inline fun FirFunctionCall.forAllReifiedTypeParameters(block: (ConeKotlinType, FirTypeProjectionWithVariance) -> Unit) {
     val functionSymbol = calleeReference.toResolvedNamedFunctionSymbol() ?: return
 
-    for ((typeParameterSymbol, typeArgument) in functionSymbol.typeParameterSymbols.zip(typeArguments)) {
+    functionSymbol.typeParameterSymbols.zipLet(typeArguments) { typeParameterSymbol, typeArgument ->
         if (typeParameterSymbol.isReified && typeArgument is FirTypeProjectionWithVariance) {
-            val type = typeArgument.typeRef.coneTypeOrNull ?: continue
-            block(type, typeArgument)
+            typeArgument.typeRef.coneTypeOrNull?.let { block(it, typeArgument) }
         }
     }
 }
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt
index 279568de..9e96070 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt
@@ -5,6 +5,8 @@
 
 package org.jetbrains.kotlin.fir.types
 
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
+
 object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
     private val ConeKotlinType.priority : Int
         get() = when (this) {
@@ -53,7 +55,7 @@
         if (sizeDiff != 0) {
             return sizeDiff
         }
-        for ((aTypeProjection, bTypeProjection) in a.zip(b)) {
+        a.zipLet(b) { aTypeProjection, bTypeProjection ->
             val typeProjectionDiff = compare(aTypeProjection, bTypeProjection)
             if (typeProjectionDiff != 0) {
                 return typeProjectionDiff
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeRefComparator.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeRefComparator.kt
index 4efce62..827d613 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeRefComparator.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeRefComparator.kt
@@ -7,6 +7,7 @@
 
 import org.jetbrains.kotlin.fir.render
 import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
+import org.jetbrains.kotlin.utils.addToStdlib.zipLet
 
 object FirTypeRefComparator : Comparator<FirTypeRef> {
     private val FirTypeRef.priority : Int
@@ -32,7 +33,7 @@
                 if (qualifierSizeDiff != 0) {
                     return qualifierSizeDiff
                 }
-                for ((aQualifier, bQualifier) in a.qualifier.zip(b.qualifier)) {
+                a.qualifier.zipLet(b.qualifier) { aQualifier, bQualifier ->
                     val qualifierNameDiff = aQualifier.name.compareTo(bQualifier.name)
                     if (qualifierNameDiff != 0) {
                         return qualifierNameDiff
@@ -42,8 +43,7 @@
                     if (typeArgumentSizeDiff != 0) {
                         return typeArgumentSizeDiff
                     }
-                    val typeArguments = aQualifier.typeArgumentList.typeArguments.zip(bQualifier.typeArgumentList.typeArguments)
-                    for ((aTypeArgument, bTypeArgument) in typeArguments) {
+                    aQualifier.typeArgumentList.typeArguments.zipLet(bQualifier.typeArgumentList.typeArguments) { aTypeArgument, bTypeArgument ->
                         val typeArgumentDiff = FirTypeProjectionComparator.compare(aTypeArgument, bTypeArgument)
                         if (typeArgumentDiff != 0) {
                             return typeArgumentDiff
diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt
index 0a47bb2..bee1de4 100644
--- a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt
+++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt
@@ -398,4 +398,24 @@
 inline fun <V : Any> KMutableProperty0<V?>.getOrSetIfNull(compute: () -> V): V =
     this.get() ?: compute().also {
         this.set(it)
-    }
\ No newline at end of file
+    }
+
+fun <T, R> List<T>.zipToMap(other: List<R>): Map<T, R> {
+    return buildMap {
+        zipLet(other) { t1, t2 ->
+            put(t1, t2)
+        }
+    }
+}
+
+inline fun <T, R> List<T>.zipLet(other: List<R>, action: (a: T, b: R) -> Unit) {
+    for (i in 0 until minOf(size, other.size)) {
+        action(this[i], other[i])
+    }
+}
+
+inline fun <T, R> Array<T>.zipLet(other: Array<R>, action: (a: T, b: R) -> Unit) {
+    for (i in 0 until minOf(size, other.size)) {
+        action(this[i], other[i])
+    }
+}
\ No newline at end of file