Cache type corresponding to type variable

This commit is contained in:
Svetlana Isakova
2015-06-29 20:10:30 +03:00
parent db8085c399
commit ac578f7e5b
4 changed files with 41 additions and 31 deletions
@@ -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()
}
@@ -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? {