From 13abc265ad9dd3bdc8194fef93607dced3b4b722 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 2 Nov 2015 15:56:02 +0300 Subject: [PATCH] First steps to make distinction between variables and descriptors in ConstraintSystem A type variable is an entity, the value of which should be solved by the system; a descriptor is an actual TypeParameterDescriptor declaration --- .../kotlin/diagnostics/rendering/Renderers.kt | 4 +- .../calls/inference/ConstraintSystem.kt | 23 ++++++----- .../inference/ConstraintSystemBuilderImpl.kt | 38 +++++++++---------- .../calls/inference/ConstraintSystemImpl.kt | 31 ++++++++------- .../calls/inference/ConstraintsUtil.java | 7 ++-- .../jetbrains/kotlin/idea/util/FuzzyType.kt | 2 +- 6 files changed, 56 insertions(+), 49 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 36981001b05..f64820ee648 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt @@ -225,7 +225,7 @@ public object Renderers { inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer ): TabledDescriptorRenderer { var firstUnknownParameter: TypeParameterDescriptor? = null - for (typeParameter in inferenceErrorData.constraintSystem.typeVariables) { + for (typeParameter in inferenceErrorData.constraintSystem.typeParameterDescriptors) { if (inferenceErrorData.constraintSystem.getTypeBounds(typeParameter).values.isEmpty()) { firstUnknownParameter = typeParameter break @@ -362,7 +362,7 @@ public object Renderers { public val RENDER_COLLECTION_OF_TYPES: Renderer> = Renderer { renderTypes(it) } private fun renderConstraintSystem(constraintSystem: ConstraintSystem, renderTypeBounds: Renderer): String { - val typeVariables = constraintSystem.typeVariables + val typeVariables = constraintSystem.typeParameterDescriptors val typeBounds = linkedSetOf() for (variable in typeVariables) { typeBounds.add(constraintSystem.getTypeBounds(variable)) 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 571eb610320..560b0ec2e7f 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 @@ -24,18 +24,23 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeSubstitutor interface ConstraintSystem { - /** - * Returns a set of all non-external registered type variables. - */ - val typeVariables: Set - val status: ConstraintSystemStatus /** - * Returns the resulting type constraints of solving the constraint system for specific type variable. - * Throws IllegalArgumentException if the type variable was not registered. + * Returns a set of all non-external type parameter descriptors. */ - fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds + val typeParameterDescriptors: Set + + /** + * Returns a set of all registered type variables. + */ + val typeVariables: Set + + /** + * Returns the resulting type constraints of solving the constraint system for specific type parameter descriptor. + * Throws IllegalArgumentException if the type parameter descriptor is not known to the system. + */ + fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBounds /** * Returns the result of solving the constraint system (mapping from the type variable to the resulting type projection). @@ -65,7 +70,7 @@ interface ConstraintSystem { */ fun registerTypeVariables( typeVariables: Collection, - mapToOriginal: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it }, + mapToDescriptor: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it }, external: Boolean = false ) 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 85e4ad5cf4b..7cc143db9df 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 @@ -54,15 +54,15 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder { internal val usedInBounds = HashMap>() internal val errors = ArrayList() internal val initialConstraints = ArrayList() - internal val originalToVariables = LinkedHashMap() - internal val variablesToOriginal = LinkedHashMap() + internal val descriptorToVariable = LinkedHashMap() + internal val variableToDescriptor = LinkedHashMap() - private val originalToVariablesSubstitutor: TypeSubstitutor by lazy { + private val descriptorToVariableSubstitutor: TypeSubstitutor by lazy { TypeSubstitutor.create(object : TypeConstructorSubstitution() { override fun get(key: TypeConstructor): TypeProjection? { val descriptor = key.declarationDescriptor if (descriptor !is TypeParameterDescriptor) return null - val typeParameterDescriptor = originalToVariables[descriptor] ?: return null + val typeParameterDescriptor = descriptorToVariable[descriptor] ?: return null return TypeProjectionImpl(typeParameterDescriptor.defaultType) } }) @@ -70,16 +70,16 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder { override fun registerTypeVariables( typeVariables: Collection, - mapToOriginal: (TypeParameterDescriptor) -> TypeParameterDescriptor, + mapToDescriptor: (TypeParameterDescriptor) -> TypeParameterDescriptor, external: Boolean ) { if (external) externalTypeParameters.addAll(typeVariables) for (typeVariable in typeVariables) { allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable)) - val original = mapToOriginal(typeVariable) - originalToVariables[original] = typeVariable - variablesToOriginal[typeVariable] = original + val descriptor = mapToDescriptor(typeVariable) + descriptorToVariable[descriptor] = typeVariable + variableToDescriptor[typeVariable] = descriptor } for ((typeVariable, typeBounds) in allTypeParameterBounds) { for (declaredUpperBound in typeVariable.upperBounds) { @@ -102,18 +102,18 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder { internal 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 isMyTypeVariable(it) } + }.filterNotNull().filter { if (original) it in descriptorToVariable.keys else isMyTypeVariable(it) } } override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) { if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return - val newSubjectType = originalToVariablesSubstitutor.substitute(subjectType, Variance.INVARIANT) + val newSubjectType = descriptorToVariableSubstitutor.substitute(subjectType, Variance.INVARIANT) addConstraint(SUB_TYPE, newSubjectType, constrainingType, ConstraintContext(constraintPosition, initial = true)) } override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) { - val newSubjectType = originalToVariablesSubstitutor.substitute(subjectType, Variance.INVARIANT) + val newSubjectType = descriptorToVariableSubstitutor.substitute(subjectType, Variance.INVARIANT) addConstraint(SUB_TYPE, constrainingType, newSubjectType, ConstraintContext(constraintPosition, initial = true)) } @@ -332,15 +332,13 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder { internal fun getBoundsUsedIn(typeVariable: TypeParameterDescriptor): List = usedInBounds[typeVariable] ?: emptyList() - internal fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl { - val variableForOriginal = originalToVariables[typeVariable] - if (variableForOriginal != null && variableForOriginal != typeVariable) { - return getTypeBounds(variableForOriginal) + internal fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBoundsImpl { + val variable = descriptorToVariable[descriptor] + if (variable != null && variable != descriptor) { + return getTypeBounds(variable) } - if (!isMyTypeVariable(typeVariable)) { - throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable") - } - return allTypeParameterBounds[typeVariable]!! + return allTypeParameterBounds[descriptor] ?: + throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $descriptor") } private fun isMyTypeVariable(typeVariable: TypeParameterDescriptor) = allTypeParameterBounds.contains(typeVariable) @@ -378,7 +376,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder { override fun build(): ConstraintSystem { return ConstraintSystemImpl(allTypeParameterBounds, externalTypeParameters, usedInBounds, errors, initialConstraints, - originalToVariables, variablesToOriginal) + descriptorToVariable, variableToDescriptor) } } 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 e35ec6931b7..19b61c74e24 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 @@ -41,8 +41,8 @@ internal class ConstraintSystemImpl( private val usedInBounds: Map>, private val errors: List, private val initialConstraints: List, - private val originalToVariables: Map, - private val variablesToOriginal: Map + private val descriptorToVariable: Map, + private val variableToDescriptor: Map ) : ConstraintSystem { private val localTypeParameterBounds: Map get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds @@ -92,7 +92,7 @@ internal class ConstraintSystemImpl( val substitutionContext = HashMap() for ((variable, typeBounds) in typeParameterBounds) { val value = typeBounds.value - val typeParameter = if (substituteOriginal) variablesToOriginal[variable]!! else variable + val typeParameter = if (substituteOriginal) variableToDescriptor[variable]!! else variable val type = if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) value else getDefaultType(typeParameter) @@ -113,19 +113,22 @@ internal class ConstraintSystemImpl( override fun getNestedTypeVariables(type: KotlinType): List { return type.getNestedArguments().map { typeProjection -> typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor - }.filterNotNull().filter { it in typeVariables } + }.filterNotNull().filter { it in typeParameterDescriptors } } - override val typeVariables: Set - get() = originalToVariables.keys + override val typeParameterDescriptors: Set + get() = descriptorToVariable.keys - override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl { - val variableForOriginal = originalToVariables[typeVariable] - if (variableForOriginal != null && variableForOriginal != typeVariable) { - return getTypeBounds(variableForOriginal) + override val typeVariables: Set + get() = variableToDescriptor.keys + + override fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBoundsImpl { + val variable = descriptorToVariable[descriptor] + if (variable != null && variable != descriptor) { + return getTypeBounds(variable) } - return allTypeParameterBounds[typeVariable] ?: - throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable") + return allTypeParameterBounds[descriptor] ?: + throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $descriptor") } override val resultingSubstitutor: TypeSubstitutor @@ -176,8 +179,8 @@ internal class ConstraintSystemImpl( result.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) }) result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) }) - result.originalToVariables.putAll(originalToVariables) - result.variablesToOriginal.putAll(variablesToOriginal) + result.descriptorToVariable.putAll(descriptorToVariable) + result.variableToDescriptor.putAll(variableToDescriptor) return result } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java index 199ecef9e45..6f4009693e6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java @@ -31,7 +31,7 @@ import java.util.*; public class ConstraintsUtil { @Nullable public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintSystem constraintSystem) { - for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeVariables()) { + for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeParameterDescriptors()) { TypeBounds constraints = constraintSystem.getTypeBounds(typeParameter); if (constraints.getValues().size() > 1) { return typeParameter; @@ -54,7 +54,7 @@ public class ConstraintsUtil { substitutionContexts.add(context); } - for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeVariables()) { + for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeParameterDescriptors()) { if (typeParameter == firstConflictingParameter) continue; KotlinType safeType = getSafeValue(constraintSystem, typeParameter); @@ -88,7 +88,8 @@ public class ConstraintsUtil { KotlinType type = constraintSystem.getTypeBounds(typeParameter).getValue(); if (type == null) return true; for (KotlinType upperBound : typeParameter.getUpperBounds()) { - if (!substituteOtherTypeParametersInBound && TypeUtils.dependsOnTypeParameters(upperBound, constraintSystem.getTypeVariables())) { + if (!substituteOtherTypeParametersInBound && + TypeUtils.dependsOnTypeParameters(upperBound, constraintSystem.getTypeParameterDescriptors())) { continue; } KotlinType substitutedUpperBound = constraintSystem.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT); diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt index dde6b666af3..dd49561452d 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt @@ -138,7 +138,7 @@ class FuzzyType( if (otherSubstitutedType.isError) return null if (!substitutedType.checkInheritance(otherSubstitutedType)) return null - val substitution = constraintSystem.typeVariables.toMap({ it.typeConstructor }) { + val substitution = constraintSystem.typeParameterDescriptors.toMap({ it.typeConstructor }) { val type = it.defaultType val solution = substitutor.substitute(type, Variance.INVARIANT) TypeProjectionImpl(if (solution != null && !ErrorUtils.containsUninferredParameter(solution)) solution else type)