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
This commit is contained in:
Alexander Udalov
2015-11-02 15:56:02 +03:00
parent eeb925f127
commit 13abc265ad
6 changed files with 56 additions and 49 deletions
@@ -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<Collection<KotlinType>> = Renderer { renderTypes(it) }
private fun renderConstraintSystem(constraintSystem: ConstraintSystem, renderTypeBounds: Renderer<TypeBounds>): String {
val typeVariables = constraintSystem.typeVariables
val typeVariables = constraintSystem.typeParameterDescriptors
val typeBounds = linkedSetOf<TypeBounds>()
for (variable in typeVariables) {
typeBounds.add(constraintSystem.getTypeBounds(variable))
@@ -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<TypeParameterDescriptor>
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<TypeParameterDescriptor>
/**
* Returns a set of all registered type variables.
*/
val typeVariables: Set<TypeParameterDescriptor>
/**
* 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<TypeParameterDescriptor>,
mapToOriginal: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it },
mapToDescriptor: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it },
external: Boolean = false
)
@@ -54,15 +54,15 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
internal val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
internal val errors = ArrayList<ConstraintError>()
internal val initialConstraints = ArrayList<Constraint>()
internal val originalToVariables = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
internal val variablesToOriginal = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
internal val variableToDescriptor = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
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<TypeParameterDescriptor>,
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<TypeParameterDescriptor> {
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<Bound> = 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)
}
}
@@ -41,8 +41,8 @@ internal class ConstraintSystemImpl(
private val usedInBounds: Map<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>,
private val errors: List<ConstraintError>,
private val initialConstraints: List<ConstraintSystemBuilderImpl.Constraint>,
private val originalToVariables: Map<TypeParameterDescriptor, TypeParameterDescriptor>,
private val variablesToOriginal: Map<TypeParameterDescriptor, TypeParameterDescriptor>
private val descriptorToVariable: Map<TypeParameterDescriptor, TypeParameterDescriptor>,
private val variableToDescriptor: Map<TypeParameterDescriptor, TypeParameterDescriptor>
) : ConstraintSystem {
private val localTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>
get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds
@@ -92,7 +92,7 @@ internal class ConstraintSystemImpl(
val substitutionContext = HashMap<TypeParameterDescriptor, TypeProjection>()
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<TypeParameterDescriptor> {
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<TypeParameterDescriptor>
get() = originalToVariables.keys
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
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<TypeParameterDescriptor>
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
}
@@ -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);
@@ -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)