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:
@@ -225,7 +225,7 @@ public object Renderers {
|
|||||||
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer
|
||||||
): TabledDescriptorRenderer {
|
): TabledDescriptorRenderer {
|
||||||
var firstUnknownParameter: TypeParameterDescriptor? = null
|
var firstUnknownParameter: TypeParameterDescriptor? = null
|
||||||
for (typeParameter in inferenceErrorData.constraintSystem.typeVariables) {
|
for (typeParameter in inferenceErrorData.constraintSystem.typeParameterDescriptors) {
|
||||||
if (inferenceErrorData.constraintSystem.getTypeBounds(typeParameter).values.isEmpty()) {
|
if (inferenceErrorData.constraintSystem.getTypeBounds(typeParameter).values.isEmpty()) {
|
||||||
firstUnknownParameter = typeParameter
|
firstUnknownParameter = typeParameter
|
||||||
break
|
break
|
||||||
@@ -362,7 +362,7 @@ public object Renderers {
|
|||||||
public val RENDER_COLLECTION_OF_TYPES: Renderer<Collection<KotlinType>> = Renderer { renderTypes(it) }
|
public val RENDER_COLLECTION_OF_TYPES: Renderer<Collection<KotlinType>> = Renderer { renderTypes(it) }
|
||||||
|
|
||||||
private fun renderConstraintSystem(constraintSystem: ConstraintSystem, renderTypeBounds: Renderer<TypeBounds>): String {
|
private fun renderConstraintSystem(constraintSystem: ConstraintSystem, renderTypeBounds: Renderer<TypeBounds>): String {
|
||||||
val typeVariables = constraintSystem.typeVariables
|
val typeVariables = constraintSystem.typeParameterDescriptors
|
||||||
val typeBounds = linkedSetOf<TypeBounds>()
|
val typeBounds = linkedSetOf<TypeBounds>()
|
||||||
for (variable in typeVariables) {
|
for (variable in typeVariables) {
|
||||||
typeBounds.add(constraintSystem.getTypeBounds(variable))
|
typeBounds.add(constraintSystem.getTypeBounds(variable))
|
||||||
|
|||||||
+14
-9
@@ -24,18 +24,23 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
interface ConstraintSystem {
|
interface ConstraintSystem {
|
||||||
/**
|
|
||||||
* Returns a set of all non-external registered type variables.
|
|
||||||
*/
|
|
||||||
val typeVariables: Set<TypeParameterDescriptor>
|
|
||||||
|
|
||||||
val status: ConstraintSystemStatus
|
val status: ConstraintSystemStatus
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the resulting type constraints of solving the constraint system for specific type variable.
|
* Returns a set of all non-external type parameter descriptors.
|
||||||
* Throws IllegalArgumentException if the type variable was not registered.
|
|
||||||
*/
|
*/
|
||||||
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).
|
* 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(
|
fun registerTypeVariables(
|
||||||
typeVariables: Collection<TypeParameterDescriptor>,
|
typeVariables: Collection<TypeParameterDescriptor>,
|
||||||
mapToOriginal: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it },
|
mapToDescriptor: (TypeParameterDescriptor) -> TypeParameterDescriptor = { it },
|
||||||
external: Boolean = false
|
external: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+18
-20
@@ -54,15 +54,15 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
internal val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
|
internal val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
|
||||||
internal val errors = ArrayList<ConstraintError>()
|
internal val errors = ArrayList<ConstraintError>()
|
||||||
internal val initialConstraints = ArrayList<Constraint>()
|
internal val initialConstraints = ArrayList<Constraint>()
|
||||||
internal val originalToVariables = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
||||||
internal val variablesToOriginal = 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() {
|
TypeSubstitutor.create(object : TypeConstructorSubstitution() {
|
||||||
override fun get(key: TypeConstructor): TypeProjection? {
|
override fun get(key: TypeConstructor): TypeProjection? {
|
||||||
val descriptor = key.declarationDescriptor
|
val descriptor = key.declarationDescriptor
|
||||||
if (descriptor !is TypeParameterDescriptor) return null
|
if (descriptor !is TypeParameterDescriptor) return null
|
||||||
val typeParameterDescriptor = originalToVariables[descriptor] ?: return null
|
val typeParameterDescriptor = descriptorToVariable[descriptor] ?: return null
|
||||||
return TypeProjectionImpl(typeParameterDescriptor.defaultType)
|
return TypeProjectionImpl(typeParameterDescriptor.defaultType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -70,16 +70,16 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
|
|
||||||
override fun registerTypeVariables(
|
override fun registerTypeVariables(
|
||||||
typeVariables: Collection<TypeParameterDescriptor>,
|
typeVariables: Collection<TypeParameterDescriptor>,
|
||||||
mapToOriginal: (TypeParameterDescriptor) -> TypeParameterDescriptor,
|
mapToDescriptor: (TypeParameterDescriptor) -> TypeParameterDescriptor,
|
||||||
external: Boolean
|
external: Boolean
|
||||||
) {
|
) {
|
||||||
if (external) externalTypeParameters.addAll(typeVariables)
|
if (external) externalTypeParameters.addAll(typeVariables)
|
||||||
|
|
||||||
for (typeVariable in typeVariables) {
|
for (typeVariable in typeVariables) {
|
||||||
allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable))
|
allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable))
|
||||||
val original = mapToOriginal(typeVariable)
|
val descriptor = mapToDescriptor(typeVariable)
|
||||||
originalToVariables[original] = typeVariable
|
descriptorToVariable[descriptor] = typeVariable
|
||||||
variablesToOriginal[typeVariable] = original
|
variableToDescriptor[typeVariable] = descriptor
|
||||||
}
|
}
|
||||||
for ((typeVariable, typeBounds) in allTypeParameterBounds) {
|
for ((typeVariable, typeBounds) in allTypeParameterBounds) {
|
||||||
for (declaredUpperBound in typeVariable.upperBounds) {
|
for (declaredUpperBound in typeVariable.upperBounds) {
|
||||||
@@ -102,18 +102,18 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
internal fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor> {
|
internal fun getNestedTypeVariables(type: KotlinType, original: Boolean): List<TypeParameterDescriptor> {
|
||||||
return type.getNestedArguments().map { typeProjection ->
|
return type.getNestedArguments().map { typeProjection ->
|
||||||
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
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) {
|
override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
||||||
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
|
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))
|
addConstraint(SUB_TYPE, newSubjectType, constrainingType, ConstraintContext(constraintPosition, initial = true))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addSubtypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
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))
|
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 getBoundsUsedIn(typeVariable: TypeParameterDescriptor): List<Bound> = usedInBounds[typeVariable] ?: emptyList()
|
||||||
|
|
||||||
internal fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl {
|
internal fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBoundsImpl {
|
||||||
val variableForOriginal = originalToVariables[typeVariable]
|
val variable = descriptorToVariable[descriptor]
|
||||||
if (variableForOriginal != null && variableForOriginal != typeVariable) {
|
if (variable != null && variable != descriptor) {
|
||||||
return getTypeBounds(variableForOriginal)
|
return getTypeBounds(variable)
|
||||||
}
|
}
|
||||||
if (!isMyTypeVariable(typeVariable)) {
|
return allTypeParameterBounds[descriptor] ?:
|
||||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $descriptor")
|
||||||
}
|
|
||||||
return allTypeParameterBounds[typeVariable]!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isMyTypeVariable(typeVariable: TypeParameterDescriptor) = allTypeParameterBounds.contains(typeVariable)
|
private fun isMyTypeVariable(typeVariable: TypeParameterDescriptor) = allTypeParameterBounds.contains(typeVariable)
|
||||||
@@ -378,7 +376,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
|
|
||||||
override fun build(): ConstraintSystem {
|
override fun build(): ConstraintSystem {
|
||||||
return ConstraintSystemImpl(allTypeParameterBounds, externalTypeParameters, usedInBounds, errors, initialConstraints,
|
return ConstraintSystemImpl(allTypeParameterBounds, externalTypeParameters, usedInBounds, errors, initialConstraints,
|
||||||
originalToVariables, variablesToOriginal)
|
descriptorToVariable, variableToDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-14
@@ -41,8 +41,8 @@ internal class ConstraintSystemImpl(
|
|||||||
private val usedInBounds: Map<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>,
|
private val usedInBounds: Map<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>,
|
||||||
private val errors: List<ConstraintError>,
|
private val errors: List<ConstraintError>,
|
||||||
private val initialConstraints: List<ConstraintSystemBuilderImpl.Constraint>,
|
private val initialConstraints: List<ConstraintSystemBuilderImpl.Constraint>,
|
||||||
private val originalToVariables: Map<TypeParameterDescriptor, TypeParameterDescriptor>,
|
private val descriptorToVariable: Map<TypeParameterDescriptor, TypeParameterDescriptor>,
|
||||||
private val variablesToOriginal: Map<TypeParameterDescriptor, TypeParameterDescriptor>
|
private val variableToDescriptor: Map<TypeParameterDescriptor, TypeParameterDescriptor>
|
||||||
) : ConstraintSystem {
|
) : ConstraintSystem {
|
||||||
private val localTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>
|
private val localTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>
|
||||||
get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds
|
get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds
|
||||||
@@ -92,7 +92,7 @@ internal class ConstraintSystemImpl(
|
|||||||
val substitutionContext = HashMap<TypeParameterDescriptor, TypeProjection>()
|
val substitutionContext = HashMap<TypeParameterDescriptor, TypeProjection>()
|
||||||
for ((variable, typeBounds) in typeParameterBounds) {
|
for ((variable, typeBounds) in typeParameterBounds) {
|
||||||
val value = typeBounds.value
|
val value = typeBounds.value
|
||||||
val typeParameter = if (substituteOriginal) variablesToOriginal[variable]!! else variable
|
val typeParameter = if (substituteOriginal) variableToDescriptor[variable]!! else variable
|
||||||
val type =
|
val type =
|
||||||
if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) value
|
if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) value
|
||||||
else getDefaultType(typeParameter)
|
else getDefaultType(typeParameter)
|
||||||
@@ -113,19 +113,22 @@ internal class ConstraintSystemImpl(
|
|||||||
override fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> {
|
override fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> {
|
||||||
return type.getNestedArguments().map { typeProjection ->
|
return type.getNestedArguments().map { typeProjection ->
|
||||||
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
typeProjection.type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||||
}.filterNotNull().filter { it in typeVariables }
|
}.filterNotNull().filter { it in typeParameterDescriptors }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val typeVariables: Set<TypeParameterDescriptor>
|
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
||||||
get() = originalToVariables.keys
|
get() = descriptorToVariable.keys
|
||||||
|
|
||||||
override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl {
|
override val typeVariables: Set<TypeParameterDescriptor>
|
||||||
val variableForOriginal = originalToVariables[typeVariable]
|
get() = variableToDescriptor.keys
|
||||||
if (variableForOriginal != null && variableForOriginal != typeVariable) {
|
|
||||||
return getTypeBounds(variableForOriginal)
|
override fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBoundsImpl {
|
||||||
|
val variable = descriptorToVariable[descriptor]
|
||||||
|
if (variable != null && variable != descriptor) {
|
||||||
|
return getTypeBounds(variable)
|
||||||
}
|
}
|
||||||
return allTypeParameterBounds[typeVariable] ?:
|
return allTypeParameterBounds[descriptor] ?:
|
||||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
override val resultingSubstitutor: TypeSubstitutor
|
override val resultingSubstitutor: TypeSubstitutor
|
||||||
@@ -176,8 +179,8 @@ internal class ConstraintSystemImpl(
|
|||||||
result.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) })
|
result.errors.addAll(errors.filter { filterConstraintPosition(it.constraintPosition) })
|
||||||
|
|
||||||
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
|
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
|
||||||
result.originalToVariables.putAll(originalToVariables)
|
result.descriptorToVariable.putAll(descriptorToVariable)
|
||||||
result.variablesToOriginal.putAll(variablesToOriginal)
|
result.variableToDescriptor.putAll(variableToDescriptor)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -31,7 +31,7 @@ import java.util.*;
|
|||||||
public class ConstraintsUtil {
|
public class ConstraintsUtil {
|
||||||
@Nullable
|
@Nullable
|
||||||
public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintSystem constraintSystem) {
|
public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintSystem constraintSystem) {
|
||||||
for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeVariables()) {
|
for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeParameterDescriptors()) {
|
||||||
TypeBounds constraints = constraintSystem.getTypeBounds(typeParameter);
|
TypeBounds constraints = constraintSystem.getTypeBounds(typeParameter);
|
||||||
if (constraints.getValues().size() > 1) {
|
if (constraints.getValues().size() > 1) {
|
||||||
return typeParameter;
|
return typeParameter;
|
||||||
@@ -54,7 +54,7 @@ public class ConstraintsUtil {
|
|||||||
substitutionContexts.add(context);
|
substitutionContexts.add(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeVariables()) {
|
for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeParameterDescriptors()) {
|
||||||
if (typeParameter == firstConflictingParameter) continue;
|
if (typeParameter == firstConflictingParameter) continue;
|
||||||
|
|
||||||
KotlinType safeType = getSafeValue(constraintSystem, typeParameter);
|
KotlinType safeType = getSafeValue(constraintSystem, typeParameter);
|
||||||
@@ -88,7 +88,8 @@ public class ConstraintsUtil {
|
|||||||
KotlinType type = constraintSystem.getTypeBounds(typeParameter).getValue();
|
KotlinType type = constraintSystem.getTypeBounds(typeParameter).getValue();
|
||||||
if (type == null) return true;
|
if (type == null) return true;
|
||||||
for (KotlinType upperBound : typeParameter.getUpperBounds()) {
|
for (KotlinType upperBound : typeParameter.getUpperBounds()) {
|
||||||
if (!substituteOtherTypeParametersInBound && TypeUtils.dependsOnTypeParameters(upperBound, constraintSystem.getTypeVariables())) {
|
if (!substituteOtherTypeParametersInBound &&
|
||||||
|
TypeUtils.dependsOnTypeParameters(upperBound, constraintSystem.getTypeParameterDescriptors())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
KotlinType substitutedUpperBound = constraintSystem.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT);
|
KotlinType substitutedUpperBound = constraintSystem.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT);
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class FuzzyType(
|
|||||||
if (otherSubstitutedType.isError) return null
|
if (otherSubstitutedType.isError) return null
|
||||||
if (!substitutedType.checkInheritance(otherSubstitutedType)) 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 type = it.defaultType
|
||||||
val solution = substitutor.substitute(type, Variance.INVARIANT)
|
val solution = substitutor.substitute(type, Variance.INVARIANT)
|
||||||
TypeProjectionImpl(if (solution != null && !ErrorUtils.containsUninferredParameter(solution)) solution else type)
|
TypeProjectionImpl(if (solution != null && !ErrorUtils.containsUninferredParameter(solution)) solution else type)
|
||||||
|
|||||||
Reference in New Issue
Block a user