From d320922e08bb1cbe2a3a06e06f8ff977de563a25 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 28 Oct 2015 23:12:21 +0300 Subject: [PATCH] Add more methods to interface ConstraintSystem To minimize usages of ConstraintSystemImpl --- .../kotlin/diagnostics/rendering/Renderers.kt | 6 +++--- .../kotlin/resolve/calls/CallCompleter.kt | 8 +++----- .../kotlin/resolve/calls/CallResolverUtil.kt | 8 ++------ .../resolve/calls/GenericCandidateResolver.kt | 7 +++---- .../calls/inference/ConstraintSystem.kt | 4 ++++ .../calls/inference/ConstraintSystemImpl.kt | 19 ++++++++++--------- .../calls/inference/ConstraintSystemStatus.kt | 2 ++ .../inference/constraintIncorporation.kt | 14 ++++++++------ 8 files changed, 35 insertions(+), 33 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt index 5dcadbfba12..e3ed648e851 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt @@ -207,7 +207,7 @@ public object Renderers { public fun renderParameterConstraintError( inferenceErrorData: InferenceErrorData, renderer: TabledDescriptorRenderer ): TabledDescriptorRenderer { - val constraintErrors = (inferenceErrorData.constraintSystem as ConstraintSystemImpl).constraintErrors + val constraintErrors = inferenceErrorData.constraintSystem.getStatus().constraintErrors val errorPositions = constraintErrors.filter { it is ParameterConstraintError }.map { it.constraintPosition } return renderer.table( TabledDescriptorRenderer @@ -308,8 +308,8 @@ public object Renderers { public fun renderCannotCaptureTypeParameterError( inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer ): TabledDescriptorRenderer { - val constraintSystem = inferenceErrorData.constraintSystem as ConstraintSystemImpl - val errors = constraintSystem.constraintErrors + val constraintSystem = inferenceErrorData.constraintSystem + val errors = constraintSystem.getStatus().constraintErrors val typeParameterWithCapturedConstraint = (errors.firstOrNull { it is CannotCapture } as? CannotCapture)?.typeVariable if (typeParameterWithCapturedConstraint == null) { LOG.error(renderDebugMessage("An error 'cannot capture type parameter' is not found in errors", inferenceErrorData)) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index 890b496c658..70d64c74077 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem -import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.* import org.jetbrains.kotlin.resolve.calls.inference.filterConstraintsOut @@ -149,7 +148,7 @@ public class CallCompleter( val returnType = getCandidateDescriptor().getReturnType() if (returnType != null) { - getConstraintSystem()!!.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION.position()) + constraintSystem!!.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION.position()) } val constraintSystemCompleter = trace[CONSTRAINT_SYSTEM_COMPLETER, getCall().getCalleeExpression()] @@ -172,10 +171,9 @@ public class CallCompleter( } } - val constraintSystem = getConstraintSystem() as ConstraintSystemImpl - constraintSystem.fixVariables() + constraintSystem!!.fixVariables() - setResultingSubstitutor(getConstraintSystem()!!.getResultingSubstitutor()) + setResultingSubstitutor(constraintSystem!!.getResultingSubstitutor()) } private fun MutableResolvedCall.updateResolutionStatusFromConstraintSystem( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt index a250b78debd..ad6243ecf8a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem -import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.types.* @@ -70,11 +69,8 @@ private fun getReturnTypeForCallable(type: KotlinType) = type.getArguments().last().getType() private fun CallableDescriptor.hasReturnTypeDependentOnUninferredParams(constraintSystem: ConstraintSystem): Boolean { - val returnType = getReturnType() ?: return false - - val nestedTypeVariables = with (constraintSystem as ConstraintSystemImpl) { - returnType.getNestedTypeVariables() - } + val returnType = returnType ?: return false + val nestedTypeVariables = constraintSystem.getNestedTypeVariables(returnType, original = true) return nestedTypeVariables.any { constraintSystem.getTypeBounds(it).value == null } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index 35b738a95f4..0559d8b8a31 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -148,14 +148,13 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes val resultingCall = resolutionResults.resultingCall if (resultingCall.isCompleted) return false - val argumentConstraintSystem = resultingCall.constraintSystem as ConstraintSystemImpl? ?: return false + val argumentConstraintSystem = resultingCall.constraintSystem ?: return false val candidateDescriptor = resultingCall.candidateDescriptor val returnType = candidateDescriptor.returnType ?: return false - val nestedTypeVariables = with (argumentConstraintSystem) { - returnType.getNestedTypeVariables() - } + val nestedTypeVariables = argumentConstraintSystem.getNestedTypeVariables(returnType, original = true) + // we add an additional type variable only if no information is inferred for it. // otherwise we add currently inferred return type as before if (nestedTypeVariables.any { argumentConstraintSystem.getTypeBounds(it).bounds.isNotEmpty() }) return false diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt index a4f3d63939b..6a32a310586 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystem.kt @@ -88,6 +88,10 @@ public interface ConstraintSystem { public fun getPartialSubstitutor(): TypeSubstitutor public fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean = { true }): ConstraintSystem + + public fun fixVariables() + + public fun getNestedTypeVariables(type: KotlinType, original: Boolean): List } fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem { 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 421706c9e4a..d78c0a0b960 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 @@ -63,8 +63,6 @@ public class ConstraintSystemImpl : ConstraintSystem { private val usedInBounds = HashMap>() private val errors = ArrayList() - public val constraintErrors: List - get() = errors private val initialConstraints = ArrayList() @@ -106,6 +104,9 @@ public class ConstraintSystemImpl : ConstraintSystem { override fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError() = localTypeParameterBounds.values.any { it.typeVariable.hasOnlyInputTypesAnnotation() && it.value == null } + + override val constraintErrors: List + get() = errors } private fun getParameterToInferredValueMap( @@ -171,10 +172,10 @@ public class ConstraintSystemImpl : ConstraintSystem { type -> type.getConstructor().getDeclarationDescriptor() in getAllTypeVariables() } - fun KotlinType.getNestedTypeVariables(original: Boolean = true): List { - return getNestedArguments().map { typeProjection -> - typeProjection.getType().getConstructor().getDeclarationDescriptor() as? TypeParameterDescriptor - }.filterNotNull().filter { if (original) it in originalToVariables.keySet() else it in getAllTypeVariables() } + override fun getNestedTypeVariables(type: KotlinType, original: Boolean): List { + return type.getNestedArguments().map { typeProjection -> + typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor + }.filterNotNull().filter { if (original) it in originalToVariables.keys else it in getAllTypeVariables() } } override fun copy(filterConstraintPosition: (ConstraintPosition) -> Boolean): ConstraintSystem { @@ -349,7 +350,7 @@ public class ConstraintSystemImpl : ConstraintSystem { typeBounds.addBound(bound) if (!bound.isProper) { - for (dependentTypeVariable in bound.constrainingType.getNestedTypeVariables(original = false)) { + for (dependentTypeVariable in getNestedTypeVariables(bound.constrainingType, original = false)) { val dependentBounds = usedInBounds.getOrPut(dependentTypeVariable) { arrayListOf() } dependentBounds.add(bound) } @@ -489,7 +490,7 @@ public class ConstraintSystemImpl : ConstraintSystem { if (typeBounds.isFixed) return typeBounds.setFixed() - val nestedTypeVariables = typeBounds.bounds.flatMap { it.constrainingType.getNestedTypeVariables(original = false) } + val nestedTypeVariables = typeBounds.bounds.flatMap { getNestedTypeVariables(it.constrainingType, original = false) } nestedTypeVariables.forEach { fixVariable(it) } val value = typeBounds.value ?: return @@ -497,7 +498,7 @@ public class ConstraintSystemImpl : ConstraintSystem { addBound(typeVariable, value, TypeBounds.BoundKind.EXACT_BOUND, ConstraintContext(ConstraintPositionKind.FROM_COMPLETER.position())) } - fun fixVariables() { + override fun fixVariables() { // todo variables should be fixed in the right order val (external, functionTypeParameters) = getAllTypeVariables().partition { externalTypeParameters.contains(it) } external.forEach { fixVariable(it) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemStatus.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemStatus.kt index 9f635a3c8b4..a4607b2fb28 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemStatus.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemStatus.kt @@ -91,4 +91,6 @@ public interface ConstraintSystemStatus { public fun hasTypeInferenceIncorporationError(): Boolean public fun hasTypeParameterWithUnsatisfiedOnlyInputTypesError(): Boolean + + public val constraintErrors: List } 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 33584768f70..39589af44cc 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 @@ -21,12 +21,13 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.Constra import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind -import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.EXACT_BOUND -import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND -import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND +import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.* import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.CompoundConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition -import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjectionImpl +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance.INVARIANT import org.jetbrains.kotlin.types.typeUtil.getNestedArguments import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes @@ -57,7 +58,8 @@ fun ConstraintSystemImpl.incorporateBound(newBound: Bound) { addBound(getMyTypeVariable(constrainingType)!!, typeVariable.correspondingType, newBound.kind.reverse(), context) return } - constrainingType.getNestedTypeVariables().forEach { + + getNestedTypeVariables(constrainingType, original = true).forEach { val boundsForNestedVariable = getTypeBounds(it).bounds for (index in boundsForNestedVariable.indices) { generateNewBound(newBound, boundsForNestedVariable[index]) @@ -98,7 +100,7 @@ private fun ConstraintSystemImpl.generateNewBound(bound: Bound, substitution: Bo fun addNewBound(newConstrainingType: KotlinType, newBoundKind: BoundKind) { // We don't generate new recursive constraints - val nestedTypeVariables = newConstrainingType.getNestedTypeVariables(original = false) + val nestedTypeVariables = getNestedTypeVariables(newConstrainingType, original = false) if (nestedTypeVariables.contains(bound.typeVariable)) return // We don't generate constraint if a type variable was substituted twice