Introduce TypeVariable to abstract the system from descriptors
Store cached type and isExternal in type variable instead of sets in the constraint system
This commit is contained in:
@@ -381,7 +381,7 @@ public object Renderers {
|
|||||||
val renderedBound = arrow + renderer.renderType(bound.constrainingType) + if (!bound.isProper) "*" else ""
|
val renderedBound = arrow + renderer.renderType(bound.constrainingType) + if (!bound.isProper) "*" else ""
|
||||||
if (short) renderedBound else renderedBound + '(' + bound.position + ')'
|
if (short) renderedBound else renderedBound + '(' + bound.position + ')'
|
||||||
}
|
}
|
||||||
val typeVariableName = typeBounds.typeVariable.getName()
|
val typeVariableName = typeBounds.typeVariable.name
|
||||||
return if (typeBounds.bounds.isEmpty()) {
|
return if (typeBounds.bounds.isEmpty()) {
|
||||||
typeVariableName.asString()
|
typeVariableName.asString()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ class ErrorInConstrainingType(constraintPosition: ConstraintPosition): Constrain
|
|||||||
|
|
||||||
class TypeInferenceError(constraintPosition: ConstraintPosition): ConstraintError(constraintPosition)
|
class TypeInferenceError(constraintPosition: ConstraintPosition): ConstraintError(constraintPosition)
|
||||||
|
|
||||||
class CannotCapture(constraintPosition: ConstraintPosition, val typeVariable: TypeParameterDescriptor): ConstraintError(constraintPosition)
|
class CannotCapture(constraintPosition: ConstraintPosition, val typeVariable: TypeVariable): ConstraintError(constraintPosition)
|
||||||
|
|
||||||
fun newTypeInferenceOrParameterConstraintError(constraintPosition: ConstraintPosition) =
|
fun newTypeInferenceOrParameterConstraintError(constraintPosition: ConstraintPosition) =
|
||||||
if (constraintPosition.isParameter()) ParameterConstraintError(constraintPosition) else TypeInferenceError(constraintPosition)
|
if (constraintPosition.isParameter()) ParameterConstraintError(constraintPosition) else TypeInferenceError(constraintPosition)
|
||||||
+4
-4
@@ -32,17 +32,17 @@ interface ConstraintSystem {
|
|||||||
/**
|
/**
|
||||||
* Returns a set of all registered type variables.
|
* Returns a set of all registered type variables.
|
||||||
*/
|
*/
|
||||||
val typeVariables: Set<TypeParameterDescriptor>
|
val typeVariables: Set<TypeVariable>
|
||||||
|
|
||||||
fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeParameterDescriptor
|
fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable
|
||||||
|
|
||||||
fun variableToDescriptor(typeVariable: TypeParameterDescriptor): TypeParameterDescriptor
|
fun variableToDescriptor(typeVariable: TypeVariable): TypeParameterDescriptor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the resulting type constraints of solving the constraint system for specific type parameter descriptor.
|
* 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.
|
* Throws IllegalArgumentException if the type parameter descriptor is not known to the system.
|
||||||
*/
|
*/
|
||||||
fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds
|
fun getTypeBounds(typeVariable: TypeVariable): 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).
|
||||||
|
|||||||
+37
-40
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
||||||
@@ -47,22 +46,20 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
EQUAL(EXACT_BOUND)
|
EQUAL(EXACT_BOUND)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val allTypeParameterBounds = LinkedHashMap<TypeParameterDescriptor, TypeBoundsImpl>()
|
internal val allTypeParameterBounds = LinkedHashMap<TypeVariable, TypeBoundsImpl>()
|
||||||
internal val externalTypeParameters = HashSet<TypeParameterDescriptor>()
|
internal val usedInBounds = HashMap<TypeVariable, MutableList<TypeBounds.Bound>>()
|
||||||
internal val cachedTypeForVariable = HashMap<TypeParameterDescriptor, KotlinType>()
|
|
||||||
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 descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeVariable>()
|
||||||
internal val variableToDescriptor = LinkedHashMap<TypeParameterDescriptor, TypeParameterDescriptor>()
|
internal val variableToDescriptor = LinkedHashMap<TypeVariable, TypeParameterDescriptor>()
|
||||||
|
|
||||||
private val descriptorToVariableSubstitutor: 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 = descriptorToVariable[descriptor] ?: return null
|
val typeVariable = descriptorToVariable[descriptor] ?: return null
|
||||||
return TypeProjectionImpl(typeParameterDescriptor.defaultType)
|
return TypeProjectionImpl(typeVariable.type)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -70,14 +67,15 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>, external: Boolean): TypeSubstitutor {
|
override fun registerTypeVariables(typeParameters: Collection<TypeParameterDescriptor>, external: Boolean): TypeSubstitutor {
|
||||||
if (typeParameters.isEmpty()) return TypeSubstitutor.EMPTY
|
if (typeParameters.isEmpty()) return TypeSubstitutor.EMPTY
|
||||||
|
|
||||||
val typeVariables = if (external) {
|
val typeVariables = (if (external) {
|
||||||
externalTypeParameters.addAll(typeParameters)
|
|
||||||
typeParameters.toList()
|
typeParameters.toList()
|
||||||
}
|
}
|
||||||
else ArrayList<TypeParameterDescriptor>(typeParameters.size).apply {
|
else ArrayList<TypeParameterDescriptor>(typeParameters.size).apply {
|
||||||
DescriptorSubstitutor.substituteTypeParameters(
|
DescriptorSubstitutor.substituteTypeParameters(
|
||||||
typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, this
|
typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, this
|
||||||
)
|
)
|
||||||
|
}).map { typeParameter ->
|
||||||
|
TypeVariable(typeParameter, external)
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) {
|
for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) {
|
||||||
@@ -87,29 +85,28 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ((typeVariable, typeBounds) in allTypeParameterBounds) {
|
for ((typeVariable, typeBounds) in allTypeParameterBounds) {
|
||||||
for (declaredUpperBound in typeVariable.upperBounds) {
|
for (declaredUpperBound in typeVariable.freshTypeParameter.upperBounds) {
|
||||||
if (declaredUpperBound.isDefaultBound()) continue //todo remove this line (?)
|
if (declaredUpperBound.isDefaultBound()) continue //todo remove this line (?)
|
||||||
val context = ConstraintContext(TYPE_BOUND_POSITION.position(typeVariable.index))
|
val context = ConstraintContext(TYPE_BOUND_POSITION.position(typeVariable.freshTypeParameter.index))
|
||||||
addBound(typeVariable, declaredUpperBound, UPPER_BOUND, context)
|
addBound(typeVariable, declaredUpperBound, UPPER_BOUND, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeSubstitutor.create(TypeConstructorSubstitution.createByParametersMap(
|
return TypeSubstitutor.create(TypeConstructorSubstitution.createByParametersMap(
|
||||||
typeParameters.zip(TypeUtils.getDefaultTypeProjections(typeVariables)).toMap()
|
typeParameters.zip(TypeUtils.getDefaultTypeProjections(typeVariables.map { it.freshTypeParameter })).toMap()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val TypeParameterDescriptor.correspondingType: KotlinType
|
|
||||||
get() = cachedTypeForVariable.getOrPut(this) {
|
|
||||||
KotlinTypeImpl.create(Annotations.EMPTY, typeConstructor, false, listOf(), MemberScope.Empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KotlinType.isProper() = !TypeUtils.containsSpecialType(this) {
|
private fun KotlinType.isProper() = !TypeUtils.containsSpecialType(this) {
|
||||||
type -> type.constructor.declarationDescriptor.let { it is TypeParameterDescriptor && isMyTypeVariable(it) }
|
type -> type.constructor.declarationDescriptor.let { it is TypeParameterDescriptor && isMyTypeVariable(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> =
|
internal fun getNestedTypeVariables(type: KotlinType): List<TypeVariable> {
|
||||||
type.getNestedTypeParameters().filter { isMyTypeVariable(it) }
|
val allTypeVariables = allTypeParameterBounds.keys
|
||||||
|
return type.getNestedTypeParameters().map { nestedTypeParameter ->
|
||||||
|
allTypeVariables.find { it.freshTypeParameter == nestedTypeParameter }
|
||||||
|
}.filterNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
override fun addSupertypeConstraint(constrainingType: KotlinType?, subjectType: KotlinType, constraintPosition: ConstraintPosition) {
|
||||||
val newSubjectType = descriptorToVariableSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
val newSubjectType = descriptorToVariableSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
||||||
@@ -248,7 +245,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun addBound(
|
internal fun addBound(
|
||||||
typeVariable: TypeParameterDescriptor,
|
typeVariable: TypeVariable,
|
||||||
constrainingType: KotlinType,
|
constrainingType: KotlinType,
|
||||||
kind: TypeBounds.BoundKind,
|
kind: TypeBounds.BoundKind,
|
||||||
constraintContext: ConstraintContext
|
constraintContext: ConstraintContext
|
||||||
@@ -315,13 +312,13 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateTypeParameterCaptureConstraint(
|
private fun generateTypeParameterCaptureConstraint(
|
||||||
typeVariable: TypeParameterDescriptor,
|
typeVariable: TypeVariable,
|
||||||
constrainingTypeProjection: TypeProjection,
|
constrainingTypeProjection: TypeProjection,
|
||||||
constraintContext: ConstraintContext,
|
constraintContext: ConstraintContext,
|
||||||
isTypeMarkedNullable: Boolean
|
isTypeMarkedNullable: Boolean
|
||||||
) {
|
) {
|
||||||
if (!typeVariable.upperBounds.let { it.size == 1 && it.single().isDefaultBound() } &&
|
if (!typeVariable.freshTypeParameter.upperBounds.let { it.size == 1 && it.single().isDefaultBound() } &&
|
||||||
constrainingTypeProjection.projectionKind == Variance.IN_VARIANCE) {
|
constrainingTypeProjection.projectionKind == Variance.IN_VARIANCE) {
|
||||||
errors.add(CannotCapture(constraintContext.position, typeVariable))
|
errors.add(CannotCapture(constraintContext.position, typeVariable))
|
||||||
}
|
}
|
||||||
val typeProjection = if (isTypeMarkedNullable) {
|
val typeProjection = if (isTypeMarkedNullable) {
|
||||||
@@ -334,31 +331,30 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
addBound(typeVariable, capturedType, EXACT_BOUND, constraintContext)
|
addBound(typeVariable, capturedType, EXACT_BOUND, constraintContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getBoundsUsedIn(typeVariable: TypeParameterDescriptor): List<Bound> = usedInBounds[typeVariable] ?: emptyList()
|
internal fun getBoundsUsedIn(typeVariable: TypeVariable): List<Bound> = usedInBounds[typeVariable] ?: emptyList()
|
||||||
|
|
||||||
internal fun getTypeBounds(descriptor: TypeParameterDescriptor): TypeBoundsImpl {
|
internal fun getTypeBounds(variable: TypeVariable): TypeBoundsImpl {
|
||||||
val variable = descriptorToVariable[descriptor]
|
return allTypeParameterBounds[variable] ?:
|
||||||
if (variable != null && variable != descriptor) {
|
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $variable")
|
||||||
return getTypeBounds(variable)
|
|
||||||
}
|
|
||||||
return allTypeParameterBounds[descriptor] ?:
|
|
||||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $descriptor")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isMyTypeVariable(typeVariable: TypeParameterDescriptor) = allTypeParameterBounds.contains(typeVariable)
|
private fun isMyTypeVariable(typeParameter: TypeParameterDescriptor) =
|
||||||
|
allTypeParameterBounds.keys.any { it.freshTypeParameter == typeParameter }
|
||||||
|
|
||||||
internal fun isMyTypeVariable(type: KotlinType): Boolean = getMyTypeVariable(type) != null
|
internal fun isMyTypeVariable(type: KotlinType): Boolean = getMyTypeVariable(type) != null
|
||||||
|
|
||||||
internal fun getMyTypeVariable(type: KotlinType): TypeParameterDescriptor? {
|
internal fun getMyTypeVariable(type: KotlinType): TypeVariable? {
|
||||||
val typeParameterDescriptor = type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
val typeParameterDescriptor = type.constructor.declarationDescriptor as? TypeParameterDescriptor
|
||||||
return if (typeParameterDescriptor != null && isMyTypeVariable(typeParameterDescriptor)) typeParameterDescriptor else null
|
return if (typeParameterDescriptor != null)
|
||||||
|
allTypeParameterBounds.keys.find { it.freshTypeParameter == typeParameterDescriptor }
|
||||||
|
else null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun storeInitialConstraint(constraintKind: ConstraintKind, subType: KotlinType, superType: KotlinType, position: ConstraintPosition) {
|
private fun storeInitialConstraint(constraintKind: ConstraintKind, subType: KotlinType, superType: KotlinType, position: ConstraintPosition) {
|
||||||
initialConstraints.add(Constraint(constraintKind, subType, superType, position))
|
initialConstraints.add(Constraint(constraintKind, subType, superType, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixVariable(typeVariable: TypeParameterDescriptor) {
|
private fun fixVariable(typeVariable: TypeVariable) {
|
||||||
val typeBounds = getTypeBounds(typeVariable)
|
val typeBounds = getTypeBounds(typeVariable)
|
||||||
if (typeBounds.isFixed) return
|
if (typeBounds.isFixed) return
|
||||||
typeBounds.setFixed()
|
typeBounds.setFixed()
|
||||||
@@ -373,14 +369,15 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
|
|||||||
|
|
||||||
override fun fixVariables() {
|
override fun fixVariables() {
|
||||||
// todo variables should be fixed in the right order
|
// todo variables should be fixed in the right order
|
||||||
val (external, functionTypeParameters) = allTypeParameterBounds.keys.partition { it in externalTypeParameters }
|
val (external, functionTypeParameters) = allTypeParameterBounds.keys.partition { it.isExternal }
|
||||||
external.forEach { fixVariable(it) }
|
external.forEach { fixVariable(it) }
|
||||||
functionTypeParameters.forEach { fixVariable(it) }
|
functionTypeParameters.forEach { fixVariable(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(): ConstraintSystem {
|
override fun build(): ConstraintSystem {
|
||||||
return ConstraintSystemImpl(allTypeParameterBounds, externalTypeParameters, usedInBounds, errors, initialConstraints,
|
return ConstraintSystemImpl(
|
||||||
descriptorToVariable, variableToDescriptor)
|
allTypeParameterBounds, usedInBounds, errors, initialConstraints, descriptorToVariable, variableToDescriptor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-16
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.TYPE_BOUND_POSITION
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.derivedFrom
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasInternalAnnotationForResolve
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasInternalAnnotationForResolve
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isInternalAnnotationForResolve
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isInternalAnnotationForResolve
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||||
@@ -35,17 +34,15 @@ import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal class ConstraintSystemImpl(
|
internal class ConstraintSystemImpl(
|
||||||
private val allTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>,
|
private val allTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl>,
|
||||||
private val externalTypeParameters: Set<TypeParameterDescriptor>,
|
private val usedInBounds: Map<TypeVariable, 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 descriptorToVariable: Map<TypeParameterDescriptor, TypeParameterDescriptor>,
|
private val descriptorToVariable: Map<TypeParameterDescriptor, TypeVariable>,
|
||||||
private val variableToDescriptor: Map<TypeParameterDescriptor, TypeParameterDescriptor>
|
private val variableToDescriptor: Map<TypeVariable, TypeParameterDescriptor>
|
||||||
) : ConstraintSystem {
|
) : ConstraintSystem {
|
||||||
private val localTypeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>
|
private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl>
|
||||||
get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds
|
get() = allTypeParameterBounds.filterNot { it.key.isExternal }
|
||||||
else allTypeParameterBounds.filter { !externalTypeParameters.contains(it.key) }
|
|
||||||
|
|
||||||
override val status = object : ConstraintSystemStatus {
|
override val status = object : ConstraintSystemStatus {
|
||||||
// for debug ConstraintsUtil.getDebugMessageForStatus might be used
|
// for debug ConstraintsUtil.getDebugMessageForStatus might be used
|
||||||
@@ -84,14 +81,14 @@ internal class ConstraintSystemImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getParameterToInferredValueMap(
|
private fun getParameterToInferredValueMap(
|
||||||
typeParameterBounds: Map<TypeParameterDescriptor, TypeBoundsImpl>,
|
typeParameterBounds: Map<TypeVariable, TypeBoundsImpl>,
|
||||||
getDefaultType: (TypeParameterDescriptor) -> KotlinType,
|
getDefaultType: (TypeParameterDescriptor) -> KotlinType,
|
||||||
substituteOriginal: Boolean
|
substituteOriginal: Boolean
|
||||||
): Map<TypeParameterDescriptor, TypeProjection> {
|
): Map<TypeParameterDescriptor, TypeProjection> {
|
||||||
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) variableToDescriptor[variable]!! else variable
|
val typeParameter = if (substituteOriginal) variableToDescriptor[variable]!! else variable.freshTypeParameter
|
||||||
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)
|
||||||
@@ -112,16 +109,16 @@ internal class ConstraintSystemImpl(
|
|||||||
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
override val typeParameterDescriptors: Set<TypeParameterDescriptor>
|
||||||
get() = descriptorToVariable.keys
|
get() = descriptorToVariable.keys
|
||||||
|
|
||||||
override val typeVariables: Set<TypeParameterDescriptor>
|
override val typeVariables: Set<TypeVariable>
|
||||||
get() = variableToDescriptor.keys
|
get() = variableToDescriptor.keys
|
||||||
|
|
||||||
override fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeParameterDescriptor =
|
override fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable =
|
||||||
descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor")
|
descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor")
|
||||||
|
|
||||||
override fun variableToDescriptor(typeVariable: TypeParameterDescriptor): TypeParameterDescriptor =
|
override fun variableToDescriptor(typeVariable: TypeVariable): TypeParameterDescriptor =
|
||||||
variableToDescriptor[typeVariable] ?: throw IllegalArgumentException("Unknown type variable: $typeVariable")
|
variableToDescriptor[typeVariable] ?: throw IllegalArgumentException("Unknown type variable: $typeVariable")
|
||||||
|
|
||||||
override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBoundsImpl {
|
override fun getTypeBounds(typeVariable: TypeVariable): TypeBoundsImpl {
|
||||||
return allTypeParameterBounds[typeVariable] ?:
|
return allTypeParameterBounds[typeVariable] ?:
|
||||||
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
throw IllegalArgumentException("TypeParameterDescriptor is not a type variable for constraint system: $typeVariable")
|
||||||
}
|
}
|
||||||
@@ -170,7 +167,6 @@ internal class ConstraintSystemImpl(
|
|||||||
val (variable, bounds) = it
|
val (variable, bounds) = it
|
||||||
variable to bounds.filterTo(arrayListOf<TypeBounds.Bound>()) { filterConstraintPosition(it.position )}
|
variable to bounds.filterTo(arrayListOf<TypeBounds.Bound>()) { filterConstraintPosition(it.position )}
|
||||||
}.toMap())
|
}.toMap())
|
||||||
result.externalTypeParameters.addAll(externalTypeParameters )
|
|
||||||
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) })
|
||||||
|
|||||||
+5
-5
@@ -30,8 +30,8 @@ import java.util.*;
|
|||||||
|
|
||||||
public class ConstraintsUtil {
|
public class ConstraintsUtil {
|
||||||
@Nullable
|
@Nullable
|
||||||
public static TypeParameterDescriptor getFirstConflictingVariable(@NotNull ConstraintSystem constraintSystem) {
|
public static TypeVariable getFirstConflictingVariable(@NotNull ConstraintSystem constraintSystem) {
|
||||||
for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
|
for (TypeVariable typeVariable : constraintSystem.getTypeVariables()) {
|
||||||
TypeBounds constraints = constraintSystem.getTypeBounds(typeVariable);
|
TypeBounds constraints = constraintSystem.getTypeBounds(typeVariable);
|
||||||
if (constraints.getValues().size() > 1) {
|
if (constraints.getValues().size() > 1) {
|
||||||
return typeVariable;
|
return typeVariable;
|
||||||
@@ -42,7 +42,7 @@ public class ConstraintsUtil {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintSystem constraintSystem) {
|
public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintSystem constraintSystem) {
|
||||||
TypeParameterDescriptor firstConflictingVariable = getFirstConflictingVariable(constraintSystem);
|
TypeVariable firstConflictingVariable = getFirstConflictingVariable(constraintSystem);
|
||||||
if (firstConflictingVariable == null) return Collections.emptyList();
|
if (firstConflictingVariable == null) return Collections.emptyList();
|
||||||
TypeParameterDescriptor firstConflictingParameter = constraintSystem.variableToDescriptor(firstConflictingVariable);
|
TypeParameterDescriptor firstConflictingParameter = constraintSystem.variableToDescriptor(firstConflictingVariable);
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ public class ConstraintsUtil {
|
|||||||
substitutionContexts.add(context);
|
substitutionContexts.add(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) {
|
for (TypeVariable typeVariable : constraintSystem.getTypeVariables()) {
|
||||||
if (typeVariable == firstConflictingVariable) continue;
|
if (typeVariable == firstConflictingVariable) continue;
|
||||||
|
|
||||||
KotlinType safeType = getSafeValue(constraintSystem, typeVariable);
|
KotlinType safeType = getSafeValue(constraintSystem, typeVariable);
|
||||||
@@ -72,7 +72,7 @@ public class ConstraintsUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static KotlinType getSafeValue(@NotNull ConstraintSystem constraintSystem, @NotNull TypeParameterDescriptor typeVariable) {
|
private static KotlinType getSafeValue(@NotNull ConstraintSystem constraintSystem, @NotNull TypeVariable typeVariable) {
|
||||||
KotlinType type = constraintSystem.getTypeBounds(typeVariable).getValue();
|
KotlinType type = constraintSystem.getTypeBounds(typeVariable).getValue();
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
return type;
|
return type;
|
||||||
|
|||||||
@@ -16,16 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind
|
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.*
|
||||||
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.constraintPosition.ConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
public interface TypeBounds {
|
public interface TypeBounds {
|
||||||
public val typeVariable: TypeParameterDescriptor
|
public val typeVariable: TypeVariable
|
||||||
|
|
||||||
public val bounds: Collection<Bound>
|
public val bounds: Collection<Bound>
|
||||||
|
|
||||||
@@ -41,13 +38,13 @@ public interface TypeBounds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Bound(
|
public class Bound(
|
||||||
public val typeVariable: TypeParameterDescriptor,
|
public val typeVariable: TypeVariable,
|
||||||
public val constrainingType: KotlinType,
|
public val constrainingType: KotlinType,
|
||||||
public val kind: BoundKind,
|
public val kind: BoundKind,
|
||||||
public val position: ConstraintPosition,
|
public val position: ConstraintPosition,
|
||||||
public val isProper: Boolean,
|
public val isProper: Boolean,
|
||||||
// to prevent infinite recursion in incorporation we store the variables that was substituted to derive this bound
|
// to prevent infinite recursion in incorporation we store the variables that was substituted to derive this bound
|
||||||
public val derivedFrom: Set<TypeParameterDescriptor>
|
public val derivedFrom: Set<TypeVariable>
|
||||||
) {
|
) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@@ -65,7 +62,7 @@ public interface TypeBounds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = typeVariable.hashCode();
|
var result = typeVariable.hashCode()
|
||||||
result = 31 * result + constrainingType.hashCode()
|
result = 31 * result + constrainingType.hashCode()
|
||||||
result = 31 * result + kind.hashCode()
|
result = 31 * result + kind.hashCode()
|
||||||
result = 31 * result + if (position.isStrong()) 1 else 0
|
result = 31 * result + if (position.isStrong()) 1 else 0
|
||||||
|
|||||||
+1
-3
@@ -16,19 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
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
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.*
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
|
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public class TypeBoundsImpl(override val typeVariable: TypeParameterDescriptor) : TypeBounds {
|
public class TypeBoundsImpl(override val typeVariable: TypeVariable) : TypeBounds {
|
||||||
override val bounds = ArrayList<Bound>()
|
override val bounds = ArrayList<Bound>()
|
||||||
|
|
||||||
private var resultValues: Collection<KotlinType>? = null
|
private var resultValues: Collection<KotlinType>? = null
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinTypeImpl
|
||||||
|
|
||||||
|
class TypeVariable(val freshTypeParameter: TypeParameterDescriptor, val isExternal: Boolean) {
|
||||||
|
val name: Name get() = freshTypeParameter.name
|
||||||
|
|
||||||
|
val type: KotlinType get() = freshTypeParameter.defaultType
|
||||||
|
|
||||||
|
fun hasOnlyInputTypesAnnotation(): Boolean =
|
||||||
|
freshTypeParameter.hasOnlyInputTypesAnnotation()
|
||||||
|
}
|
||||||
+3
-4
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.EQUAL
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.EQUAL
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.SUB_TYPE
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.SUB_TYPE
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
||||||
@@ -35,7 +34,7 @@ import java.util.*
|
|||||||
data class ConstraintContext(
|
data class ConstraintContext(
|
||||||
val position: ConstraintPosition,
|
val position: ConstraintPosition,
|
||||||
// see TypeBounds.Bound.derivedFrom
|
// see TypeBounds.Bound.derivedFrom
|
||||||
val derivedFrom: Set<TypeParameterDescriptor>? = null,
|
val derivedFrom: Set<TypeVariable>? = null,
|
||||||
val initial: Boolean = false)
|
val initial: Boolean = false)
|
||||||
|
|
||||||
fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) {
|
fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) {
|
||||||
@@ -54,7 +53,7 @@ fun ConstraintSystemBuilderImpl.incorporateBound(newBound: Bound) {
|
|||||||
val constrainingType = newBound.constrainingType
|
val constrainingType = newBound.constrainingType
|
||||||
if (isMyTypeVariable(constrainingType)) {
|
if (isMyTypeVariable(constrainingType)) {
|
||||||
val context = ConstraintContext(newBound.position, newBound.derivedFrom)
|
val context = ConstraintContext(newBound.position, newBound.derivedFrom)
|
||||||
addBound(getMyTypeVariable(constrainingType)!!, typeVariable.correspondingType, newBound.kind.reverse(), context)
|
addBound(getMyTypeVariable(constrainingType)!!, typeVariable.type, newBound.kind.reverse(), context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +91,7 @@ private fun ConstraintSystemBuilderImpl.generateNewBound(bound: Bound, substitut
|
|||||||
}
|
}
|
||||||
|
|
||||||
val newTypeProjection = TypeProjectionImpl(substitutedType)
|
val newTypeProjection = TypeProjectionImpl(substitutedType)
|
||||||
val substitutor = TypeSubstitutor.create(mapOf(substitution.typeVariable.typeConstructor to newTypeProjection))
|
val substitutor = TypeSubstitutor.create(mapOf(substitution.typeVariable.type.constructor to newTypeProjection))
|
||||||
val type = substitutor.substitute(bound.constrainingType, INVARIANT) ?: return
|
val type = substitutor.substitute(bound.constrainingType, INVARIANT) ?: return
|
||||||
|
|
||||||
val position = CompoundConstraintPosition(bound.position, substitution.position)
|
val position = CompoundConstraintPosition(bound.position, substitution.position)
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.types.TypeProjection
|
|||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun ConstraintSystem.getNestedTypeVariables(type: KotlinType): List<TypeParameterDescriptor> =
|
fun ConstraintSystem.getNestedTypeVariables(type: KotlinType): List<TypeVariable> =
|
||||||
type.getNestedTypeParameters().filter { it in typeParameterDescriptors }.map { descriptorToVariable(it) }
|
type.getNestedTypeParameters().filter { it in typeParameterDescriptors }.map { descriptorToVariable(it) }
|
||||||
|
|
||||||
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
|
fun ConstraintSystem.filterConstraintsOut(excludePositionKind: ConstraintPositionKind): ConstraintSystem {
|
||||||
|
|||||||
Reference in New Issue
Block a user