Move original descriptor to TypeVariable, minimize usages of freshTypeParameter

This commit is contained in:
Alexander Udalov
2015-11-11 16:24:22 +03:00
parent c1bd430b27
commit fc73e8c620
6 changed files with 31 additions and 39 deletions
@@ -320,7 +320,7 @@ public object Renderers {
return result return result
} }
val typeParameter = system.variableToDescriptor(typeVariableWithCapturedConstraint) val typeParameter = typeVariableWithCapturedConstraint.originalTypeParameter
val explanation: String val explanation: String
val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameter) val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameter)
@@ -36,8 +36,6 @@ interface ConstraintSystem {
fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable
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.
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.defaultProjections
import org.jetbrains.kotlin.types.typeUtil.isDefaultBound import org.jetbrains.kotlin.types.typeUtil.isDefaultBound
import java.util.* import java.util.*
@@ -51,7 +52,6 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
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, TypeVariable>() internal val descriptorToVariable = LinkedHashMap<TypeParameterDescriptor, TypeVariable>()
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() {
@@ -74,26 +74,26 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
DescriptorSubstitutor.substituteTypeParameters( DescriptorSubstitutor.substituteTypeParameters(
typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, this typeParameters.toList(), TypeSubstitution.EMPTY, typeParameters.first().containingDeclaration, this
) )
}).map { typeParameter -> }).zip(typeParameters).map {
TypeVariable(typeParameter, external) val (fresh, original) = it
TypeVariable(fresh, original, external)
} }
for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) { for ((descriptor, typeVariable) in typeParameters.zip(typeVariables)) {
allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable)) allTypeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable))
descriptorToVariable[descriptor] = typeVariable descriptorToVariable[descriptor] = typeVariable
variableToDescriptor[typeVariable] = descriptor
} }
for ((typeVariable, typeBounds) in allTypeParameterBounds) { for ((typeVariable, typeBounds) in allTypeParameterBounds) {
for (declaredUpperBound in typeVariable.freshTypeParameter.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.freshTypeParameter.index)) val context = ConstraintContext(TYPE_BOUND_POSITION.position(typeVariable.originalTypeParameter.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.map { it.freshTypeParameter })).toMap() typeParameters.zip(typeVariables.map { it.type }.defaultProjections()).toMap()
)) ))
} }
@@ -101,12 +101,8 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
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<TypeVariable> { internal fun getNestedTypeVariables(type: KotlinType): List<TypeVariable> =
val allTypeVariables = allTypeParameterBounds.keys type.getNestedTypeParameters().map { getMyTypeVariable(it) }.filterNotNull()
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)
@@ -317,7 +313,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
constraintContext: ConstraintContext, constraintContext: ConstraintContext,
isTypeMarkedNullable: Boolean isTypeMarkedNullable: Boolean
) { ) {
if (!typeVariable.freshTypeParameter.upperBounds.let { it.size == 1 && it.single().isDefaultBound() } && if (!typeVariable.originalTypeParameter.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))
} }
@@ -339,17 +335,18 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
} }
private fun isMyTypeVariable(typeParameter: TypeParameterDescriptor) = private fun isMyTypeVariable(typeParameter: TypeParameterDescriptor) =
allTypeParameterBounds.keys.any { it.freshTypeParameter == typeParameter } getMyTypeVariable(typeParameter) != null
internal fun isMyTypeVariable(type: KotlinType): Boolean = getMyTypeVariable(type) != null internal fun isMyTypeVariable(type: KotlinType): Boolean =
getMyTypeVariable(type) != null
internal fun getMyTypeVariable(type: KotlinType): TypeVariable? { internal fun getMyTypeVariable(type: KotlinType): TypeVariable? {
val typeParameterDescriptor = type.constructor.declarationDescriptor as? TypeParameterDescriptor return getMyTypeVariable(type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return null)
return if (typeParameterDescriptor != null)
allTypeParameterBounds.keys.find { it.freshTypeParameter == typeParameterDescriptor }
else null
} }
private fun getMyTypeVariable(typeParameter: TypeParameterDescriptor): TypeVariable? =
allTypeParameterBounds.keys.find { it.freshTypeParameter == typeParameter }
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))
} }
@@ -375,9 +372,7 @@ class ConstraintSystemBuilderImpl : ConstraintSystem.Builder {
} }
override fun build(): ConstraintSystem { override fun build(): ConstraintSystem {
return ConstraintSystemImpl( return ConstraintSystemImpl(allTypeParameterBounds, usedInBounds, errors, initialConstraints, descriptorToVariable)
allTypeParameterBounds, usedInBounds, errors, initialConstraints, descriptorToVariable, variableToDescriptor
)
} }
} }
@@ -38,8 +38,7 @@ internal class ConstraintSystemImpl(
private val usedInBounds: Map<TypeVariable, MutableList<TypeBounds.Bound>>, private val usedInBounds: Map<TypeVariable, 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, TypeVariable>, private val descriptorToVariable: Map<TypeParameterDescriptor, TypeVariable>
private val variableToDescriptor: Map<TypeVariable, TypeParameterDescriptor>
) : ConstraintSystem { ) : ConstraintSystem {
private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl> private val localTypeParameterBounds: Map<TypeVariable, TypeBoundsImpl>
get() = allTypeParameterBounds.filterNot { it.key.isExternal } get() = allTypeParameterBounds.filterNot { it.key.isExternal }
@@ -88,7 +87,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) variableToDescriptor[variable]!! else variable.freshTypeParameter val typeParameter = if (substituteOriginal) variable.originalTypeParameter 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)
@@ -110,14 +109,11 @@ internal class ConstraintSystemImpl(
get() = descriptorToVariable.keys get() = descriptorToVariable.keys
override val typeVariables: Set<TypeVariable> override val typeVariables: Set<TypeVariable>
get() = variableToDescriptor.keys get() = allTypeParameterBounds.keys
override fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable = override fun descriptorToVariable(descriptor: TypeParameterDescriptor): TypeVariable =
descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor") descriptorToVariable[descriptor] ?: throw IllegalArgumentException("Unknown descriptor: $descriptor")
override fun variableToDescriptor(typeVariable: TypeVariable): TypeParameterDescriptor =
variableToDescriptor[typeVariable] ?: throw IllegalArgumentException("Unknown type variable: $typeVariable")
override fun getTypeBounds(typeVariable: TypeVariable): 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")
@@ -171,7 +167,6 @@ internal class ConstraintSystemImpl(
result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) }) result.initialConstraints.addAll(initialConstraints.filter { filterConstraintPosition(it.position) })
result.descriptorToVariable.putAll(descriptorToVariable) result.descriptorToVariable.putAll(descriptorToVariable)
result.variableToDescriptor.putAll(variableToDescriptor)
return result return result
} }
@@ -44,7 +44,7 @@ public class ConstraintsUtil {
public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintSystem constraintSystem) { public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintSystem constraintSystem) {
TypeVariable 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 = firstConflictingVariable.getOriginalTypeParameter();
Collection<KotlinType> conflictingTypes = constraintSystem.getTypeBounds(firstConflictingVariable).getValues(); Collection<KotlinType> conflictingTypes = constraintSystem.getTypeBounds(firstConflictingVariable).getValues();
@@ -61,7 +61,7 @@ public class ConstraintsUtil {
KotlinType safeType = getSafeValue(constraintSystem, typeVariable); KotlinType safeType = getSafeValue(constraintSystem, typeVariable);
for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) { for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) {
TypeProjection typeProjection = new TypeProjectionImpl(safeType); TypeProjection typeProjection = new TypeProjectionImpl(safeType);
context.put(constraintSystem.variableToDescriptor(typeVariable).getTypeConstructor(), typeProjection); context.put(typeVariable.getOriginalTypeParameter().getTypeConstructor(), typeProjection);
} }
} }
Collection<TypeSubstitutor> typeSubstitutors = new ArrayList<TypeSubstitutor>(substitutionContexts.size()); Collection<TypeSubstitutor> typeSubstitutors = new ArrayList<TypeSubstitutor>(substitutionContexts.size());
@@ -78,7 +78,7 @@ public class ConstraintsUtil {
return type; return type;
} }
//todo may be error type //todo may be error type
return TypeIntersector.getUpperBoundsAsType(constraintSystem.variableToDescriptor(typeVariable)); return TypeIntersector.getUpperBoundsAsType(typeVariable.getOriginalTypeParameter());
} }
public static boolean checkUpperBoundIsSatisfied( public static boolean checkUpperBoundIsSatisfied(
@@ -24,11 +24,15 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeImpl import org.jetbrains.kotlin.types.KotlinTypeImpl
class TypeVariable(val freshTypeParameter: TypeParameterDescriptor, val isExternal: Boolean) { class TypeVariable(
val name: Name get() = freshTypeParameter.name val freshTypeParameter: TypeParameterDescriptor,
val originalTypeParameter: TypeParameterDescriptor,
val isExternal: Boolean
) {
val name: Name get() = originalTypeParameter.name
val type: KotlinType get() = freshTypeParameter.defaultType val type: KotlinType get() = freshTypeParameter.defaultType
fun hasOnlyInputTypesAnnotation(): Boolean = fun hasOnlyInputTypesAnnotation(): Boolean =
freshTypeParameter.hasOnlyInputTypesAnnotation() originalTypeParameter.hasOnlyInputTypesAnnotation()
} }