[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