Cache type corresponding to type variable
This commit is contained in:
+27
-15
@@ -57,6 +57,8 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
get() = if (externalTypeParameters.isEmpty()) allTypeParameterBounds
|
||||
else allTypeParameterBounds.filter { !externalTypeParameters.contains(it.key) }
|
||||
|
||||
private val cachedTypeForVariable = HashMap<TypeParameterDescriptor, JetType>()
|
||||
|
||||
private val usedInBounds = HashMap<TypeParameterDescriptor, MutableList<TypeBounds.Bound>>()
|
||||
|
||||
private val errors = ArrayList<ConstraintError>()
|
||||
@@ -139,12 +141,16 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
for (declaredUpperBound in typeVariable.getUpperBounds()) {
|
||||
if (KotlinBuiltIns.getInstance().getNullableAnyType() == declaredUpperBound) continue //todo remove this line (?)
|
||||
val position = TYPE_BOUND_POSITION.position(typeVariable.getIndex())
|
||||
val variableType = JetTypeImpl(Annotations.EMPTY, typeVariable.getTypeConstructor(), false, listOf(), JetScope.Empty)
|
||||
addBound(variableType, Bound(declaredUpperBound, UPPER_BOUND, position, declaredUpperBound.isProper()))
|
||||
addBound(typeVariable, declaredUpperBound, UPPER_BOUND, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val TypeParameterDescriptor.correspondingType: JetType
|
||||
get() = cachedTypeForVariable.getOrPut(this) {
|
||||
JetTypeImpl(Annotations.EMPTY, this.getTypeConstructor(), false, listOf(), JetScope.Empty)
|
||||
}
|
||||
|
||||
fun JetType.isProper() = !TypeUtils.containsSpecialType(this) {
|
||||
type -> type.getConstructor().getDeclarationDescriptor() in getAllTypeVariables()
|
||||
}
|
||||
@@ -321,8 +327,14 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
|
||||
}
|
||||
|
||||
fun addBound(variable: JetType, bound: Bound) {
|
||||
val typeBounds = getTypeBounds(variable)
|
||||
fun addBound(
|
||||
typeVariable: TypeParameterDescriptor,
|
||||
constrainingType: JetType,
|
||||
kind: TypeBounds.BoundKind,
|
||||
position: ConstraintPosition
|
||||
) {
|
||||
val bound = Bound(typeVariable, constrainingType, kind, position, constrainingType.isProper())
|
||||
val typeBounds = getTypeBounds(typeVariable)
|
||||
if (typeBounds.bounds.contains(bound)) return
|
||||
|
||||
typeBounds.addBound(bound)
|
||||
@@ -334,7 +346,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
}
|
||||
}
|
||||
|
||||
incorporateBound(variable, bound)
|
||||
incorporateBound(bound)
|
||||
}
|
||||
|
||||
private fun generateTypeParameterBound(
|
||||
@@ -343,6 +355,8 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
boundKind: TypeBounds.BoundKind,
|
||||
constraintPosition: ConstraintPosition
|
||||
) {
|
||||
val typeVariable = getMyTypeVariable(parameterType)!!
|
||||
|
||||
var newConstrainingType = constrainingType
|
||||
|
||||
// Here we are handling the case when T! gets a bound Foo (or Foo?)
|
||||
@@ -354,14 +368,14 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
// Foo >: T!
|
||||
// both Foo and Foo? transform to Foo! here
|
||||
if (parameterType.isFlexible()) {
|
||||
val typeVariable = parameterType.getCustomTypeVariable()
|
||||
if (typeVariable != null) {
|
||||
newConstrainingType = typeVariable.substitutionResult(constrainingType)
|
||||
val customTypeVariable = parameterType.getCustomTypeVariable()
|
||||
if (customTypeVariable != null) {
|
||||
newConstrainingType = customTypeVariable.substitutionResult(constrainingType)
|
||||
}
|
||||
}
|
||||
|
||||
if (!parameterType.isMarkedNullable() || !TypeUtils.isNullableType(newConstrainingType)) {
|
||||
addBound(parameterType, Bound(newConstrainingType, boundKind, constraintPosition, newConstrainingType.isProper()))
|
||||
addBound(typeVariable, newConstrainingType, boundKind, constraintPosition)
|
||||
return
|
||||
}
|
||||
// For parameter type T:
|
||||
@@ -369,14 +383,13 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
// constraint T? = Int! should transform to T >: Int and T <: Int!
|
||||
|
||||
// constraints T? >: Int?; T? >: Int! should transform to T >: Int
|
||||
val notNullParameterType = TypeUtils.makeNotNullable(parameterType)
|
||||
val notNullConstrainingType = TypeUtils.makeNotNullable(newConstrainingType)
|
||||
if (boundKind == EXACT_BOUND || boundKind == LOWER_BOUND) {
|
||||
addBound(notNullParameterType, Bound(notNullConstrainingType, LOWER_BOUND, constraintPosition, notNullConstrainingType.isProper()))
|
||||
addBound(typeVariable, notNullConstrainingType, LOWER_BOUND, constraintPosition)
|
||||
}
|
||||
// constraints T? <: Int?; T? <: Int! should transform to T <: Int?; T <: Int! correspondingly
|
||||
if (boundKind == EXACT_BOUND || boundKind == UPPER_BOUND) {
|
||||
addBound(notNullParameterType, Bound(newConstrainingType, UPPER_BOUND, constraintPosition, newConstrainingType.isProper()))
|
||||
addBound(typeVariable, newConstrainingType, UPPER_BOUND, constraintPosition)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +410,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
constrainingTypeProjection
|
||||
}
|
||||
val capturedType = createCapturedType(typeProjection)
|
||||
addBound(TypeUtils.makeNotNullable(parameterType), Bound(capturedType, EXACT_BOUND, constraintPosition))
|
||||
addBound(typeVariable, capturedType, EXACT_BOUND, constraintPosition)
|
||||
}
|
||||
|
||||
override fun getTypeVariables() = typeParameterBounds.keySet()
|
||||
@@ -441,8 +454,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
|
||||
val value = typeBounds.value ?: return
|
||||
|
||||
val type = JetTypeImpl(Annotations.EMPTY, typeVariable.getTypeConstructor(), false, emptyList(), JetScope.Empty)
|
||||
addBound(type, TypeBounds.Bound(value, TypeBounds.BoundKind.EXACT_BOUND, ConstraintPositionKind.FROM_COMPLETER.position()))
|
||||
addBound(typeVariable, value, TypeBounds.BoundKind.EXACT_BOUND, ConstraintPositionKind.FROM_COMPLETER.position())
|
||||
}
|
||||
|
||||
fun fixVariables() {
|
||||
|
||||
@@ -45,19 +45,19 @@ public trait TypeBounds {
|
||||
}
|
||||
|
||||
public class Bound(
|
||||
public val typeVariable: TypeParameterDescriptor,
|
||||
public val constrainingType: JetType,
|
||||
public val kind: BoundKind,
|
||||
public val position: ConstraintPosition,
|
||||
public val isProper: Boolean = true
|
||||
) {
|
||||
public var typeVariable: TypeParameterDescriptor by Delegates.notNull()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || javaClass != other.javaClass) return false
|
||||
|
||||
val bound = other as Bound
|
||||
|
||||
if (typeVariable != bound.typeVariable) return false
|
||||
if (constrainingType != bound.constrainingType) return false
|
||||
if (kind != bound.kind) return false
|
||||
|
||||
@@ -67,7 +67,8 @@ public trait TypeBounds {
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = constrainingType.hashCode()
|
||||
var result = typeVariable.hashCode();
|
||||
result = 31 * result + constrainingType.hashCode()
|
||||
result = 31 * result + kind.hashCode()
|
||||
result = 31 * result + if (position.isStrong()) 1 else 0
|
||||
return result
|
||||
|
||||
@@ -49,7 +49,9 @@ public class TypeBoundsImpl(
|
||||
|
||||
public fun addBound(bound: Bound) {
|
||||
resultValues = null
|
||||
bound.typeVariable = typeVariable
|
||||
assert(bound.typeVariable == typeVariable) {
|
||||
"$bound is added for incorrect type variable ${bound.typeVariable.getName()}. Expected: ${typeVariable.getName()}"
|
||||
}
|
||||
bounds.add(bound)
|
||||
}
|
||||
|
||||
@@ -202,9 +204,7 @@ fun Collection<Bound>.substitute(substituteTypeVariable: (TypeParameterDescripto
|
||||
it.constrainingType
|
||||
}
|
||||
substitutedType?.let { type ->
|
||||
val newBound = Bound(type, it.kind, it.position, it.isProper)
|
||||
newBound.typeVariable = substituteTypeVariable(it.typeVariable) ?: it.typeVariable
|
||||
newBound
|
||||
Bound(substituteTypeVariable(it.typeVariable) ?: it.typeVariable, type, it.kind, it.position, it.isProper)
|
||||
}
|
||||
}.filterNotNull()
|
||||
}
|
||||
+6
-9
@@ -34,8 +34,8 @@ import org.jetbrains.kotlin.types.Variance.IN_VARIANCE
|
||||
import org.jetbrains.kotlin.types.typeUtil.getNestedTypeArguments
|
||||
import java.util.ArrayList
|
||||
|
||||
fun ConstraintSystemImpl.incorporateBound(variable: JetType, newBound: Bound) {
|
||||
val typeVariable = getMyTypeVariable(variable)!!
|
||||
fun ConstraintSystemImpl.incorporateBound(newBound: Bound) {
|
||||
val typeVariable = newBound.typeVariable
|
||||
val typeBounds = getTypeBounds(typeVariable)
|
||||
|
||||
for (oldBoundIndex in typeBounds.bounds.indices) {
|
||||
@@ -44,20 +44,18 @@ fun ConstraintSystemImpl.incorporateBound(variable: JetType, newBound: Bound) {
|
||||
val boundsUsedIn = getBoundsUsedIn(typeVariable)
|
||||
for (index in boundsUsedIn.indices) {
|
||||
val boundUsedIn = boundsUsedIn[index]
|
||||
val type = JetTypeImpl(Annotations.EMPTY, boundUsedIn.typeVariable.getTypeConstructor(), false, listOf(), JetScope.Empty)
|
||||
generateNewBound(type, boundUsedIn, newBound)
|
||||
generateNewBound(boundUsedIn, newBound)
|
||||
}
|
||||
|
||||
val constrainingType = newBound.constrainingType
|
||||
if (isMyTypeVariable(constrainingType)) {
|
||||
val bound = Bound(variable, newBound.kind.reverse(), newBound.position, isProper = false)
|
||||
addBound(constrainingType, bound)
|
||||
addBound(getMyTypeVariable(constrainingType)!!, typeVariable.correspondingType, newBound.kind.reverse(), newBound.position)
|
||||
return
|
||||
}
|
||||
constrainingType.getNestedTypeVariables().forEach {
|
||||
val boundsForNestedVariable = getTypeBounds(it).bounds
|
||||
for (index in boundsForNestedVariable.indices) {
|
||||
generateNewBound(variable, newBound, boundsForNestedVariable[index])
|
||||
generateNewBound(newBound, boundsForNestedVariable[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +80,6 @@ private fun ConstraintSystemImpl.addConstraintFromBounds(old: Bound, new: Bound)
|
||||
}
|
||||
|
||||
private fun ConstraintSystemImpl.generateNewBound(
|
||||
variable: JetType,
|
||||
bound: Bound,
|
||||
substitution: Bound
|
||||
) {
|
||||
@@ -110,7 +107,7 @@ private fun ConstraintSystemImpl.generateNewBound(
|
||||
if (nestedTypeVariables.contains(bound.typeVariable) || nestedTypeVariables.contains(substitution.typeVariable)) return
|
||||
|
||||
val position = CompoundConstraintPosition(bound.position, substitution.position)
|
||||
addBound(variable, Bound(newConstrainingType, newKind, position, newConstrainingType.isProper()))
|
||||
addBound(bound.typeVariable, newConstrainingType, newKind, position)
|
||||
}
|
||||
|
||||
private fun computeKindOfNewBound(constrainingKind: BoundKind, substitutionVariance: Variance, substitutionKind: BoundKind): BoundKind? {
|
||||
|
||||
Reference in New Issue
Block a user