diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt index 3b2f2cc95f8..3b45e639c31 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt @@ -328,8 +328,6 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder { addBound(typeVariable, capturedType, EXACT_BOUND, constraintContext) } - internal fun getBoundsUsedIn(typeVariable: TypeVariable): List = usedInBounds[typeVariable] ?: emptyList() - internal fun getTypeBounds(variable: TypeVariable): TypeBoundsImpl { return allTypeParameterBounds[variable] ?: throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $variable") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt index 714dd87b01d..6d68013d10d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemImpl.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.resolve.calls.inference -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.EQUAL @@ -81,30 +80,23 @@ internal class ConstraintSystemImpl( private fun getParameterToInferredValueMap( typeParameterBounds: Map, - getDefaultType: (TypeParameterDescriptor) -> KotlinType, + getDefaultType: (TypeVariable) -> KotlinType, substituteOriginal: Boolean - ): Map { - val substitutionContext = HashMap() + ): Map { + val substitutionContext = HashMap() for ((variable, typeBounds) in typeParameterBounds) { val value = typeBounds.value - val typeParameter = if (substituteOriginal) variable.originalTypeParameter else variable.freshTypeParameter + val typeConstructor = + if (substituteOriginal) variable.originalTypeParameter.typeConstructor + else variable.type.constructor val type = if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) value - else getDefaultType(typeParameter) - substitutionContext.put(typeParameter, TypeProjectionImpl(type)) + else getDefaultType(variable) + substitutionContext.put(typeConstructor, TypeProjectionImpl(type)) } return substitutionContext } - private fun replaceUninferredBy( - getDefaultValue: (TypeParameterDescriptor) -> KotlinType, - substituteOriginal: Boolean - ): TypeSubstitutor { - val parameterToInferredValueMap = getParameterToInferredValueMap(allTypeParameterBounds, getDefaultValue, substituteOriginal) - val substitution = TypeConstructorSubstitution.createByParametersMap(parameterToInferredValueMap) - return SubstitutionFilteringInternalResolveAnnotations(substitution).buildSubstitutor() - } - override val typeVariables: Set get() = allTypeParameterBounds.keys @@ -114,25 +106,30 @@ internal class ConstraintSystemImpl( } override val resultingSubstitutor: TypeSubstitutor - get() = getSubstitutor(substituteOriginal = true) { ErrorUtils.createUninferredParameterType(it) } + get() = getSubstitutor(substituteOriginal = true) { ErrorUtils.createUninferredParameterType(it.originalTypeParameter) } override val currentSubstitutor: TypeSubstitutor get() = getSubstitutor(substituteOriginal = true) { TypeUtils.DONT_CARE } - private fun getSubstitutor(substituteOriginal: Boolean, getDefaultValue: (TypeParameterDescriptor) -> KotlinType) = - replaceUninferredBy(getDefaultValue, substituteOriginal).run { - TypeSubstitutor.create(SubstitutionWithCapturedTypeApproximation(this.substitution)) - } + private fun getSubstitutor(substituteOriginal: Boolean, getDefaultValue: (TypeVariable) -> KotlinType): TypeSubstitutor { + val parameterToInferredValueMap = getParameterToInferredValueMap(allTypeParameterBounds, getDefaultValue, substituteOriginal) + return TypeSubstitutor.create( + SubstitutionWithCapturedTypeApproximation( + SubstitutionFilteringInternalResolveAnnotations( + TypeConstructorSubstitution.createByConstructorsMap(parameterToInferredValueMap) + ) + ) + ) + } private class SubstitutionWithCapturedTypeApproximation(substitution: TypeSubstitution) : DelegatedTypeSubstitution(substitution) { override fun approximateCapturedTypes() = true } private fun satisfyInitialConstraints(): Boolean { - fun KotlinType.substitute(): KotlinType? { - val substitutor = getSubstitutor(substituteOriginal = false) { ErrorUtils.createUninferredParameterType(it) } - return substitutor.substitute(this, Variance.INVARIANT) ?: return null - } + val substitutor = getSubstitutor(substituteOriginal = false) { ErrorUtils.createUninferredParameterType(it.originalTypeParameter) } + fun KotlinType.substitute(): KotlinType? = substitutor.substitute(this, Variance.INVARIANT) + return initialConstraints.all { constraint -> val resultSubType = constraint.subtype.substitute()?.let { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt index 21dd34f163d..07b1b8385c7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/constraintIncorporation.kt @@ -41,10 +41,11 @@ fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) { val typeVariable = newBound.typeVariable val typeBounds = getTypeBounds(typeVariable) + // Here and afterwards we're iterating indices of the original bounds list to prevent ConcurrentModificationException for (oldBoundIndex in typeBounds.bounds.indices) { addConstraintFromBounds(typeBounds.bounds[oldBoundIndex], newBound) } - val boundsUsedIn = getBoundsUsedIn(typeVariable) + val boundsUsedIn = usedInBounds[typeVariable] ?: emptyList() for (index in boundsUsedIn.indices) { val boundUsedIn = boundsUsedIn[index] generateNewBound(boundUsedIn, newBound)