[NI] Don't recreate subtyping context every time

This commit is contained in:
Mikhail Zarechenskiy
2019-09-13 12:55:53 +03:00
parent de009a2ff2
commit e8907c078d
@@ -22,8 +22,6 @@ import org.jetbrains.kotlin.types.AbstractNullabilityChecker.hasPathByNotMarkedN
import org.jetbrains.kotlin.types.model.*
object NewCommonSuperTypeCalculator {
// TODO: Bridge for old calls
fun commonSuperType(types: List<UnwrappedType>): UnwrappedType {
return SimpleClassicTypeSystemContext.commonSuperType(types) as UnwrappedType
@@ -55,23 +53,30 @@ object NewCommonSuperTypeCalculator {
}
}
val lowerSuperType = commonSuperTypeForSimpleTypes(lowers, depth)
val contextStubTypesEqualToAnything = newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
val contextStubTypesNotEqual = newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false)
val lowerSuperType = commonSuperTypeForSimpleTypes(lowers, depth, contextStubTypesEqualToAnything, contextStubTypesNotEqual)
if (!thereIsFlexibleTypes) return lowerSuperType
val upperSuperType = commonSuperTypeForSimpleTypes(types.map { it.upperBoundIfFlexible() }, depth)
val upperSuperType = commonSuperTypeForSimpleTypes(
types.map { it.upperBoundIfFlexible() }, depth, contextStubTypesEqualToAnything, contextStubTypesNotEqual
)
return createFlexibleType(lowerSuperType, upperSuperType)
}
private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForSimpleTypes(
types: List<SimpleTypeMarker>,
depth: Int
depth: Int,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext,
contextStubTypesNotEqual: AbstractTypeCheckerContext
): SimpleTypeMarker {
// i.e. result type also should be marked nullable
val notAllNotNull =
types.any { !isStubRelatedType(it) && !AbstractNullabilityChecker.isSubtypeOfAny(contextStubTypesEqualToAnything, it) }
val notNullTypes = if (notAllNotNull) types.map { it.withNullability(false) } else types
val commonSuperType = commonSuperTypeForNotNullTypes(notNullTypes, depth)
val commonSuperType = commonSuperTypeForNotNullTypes(notNullTypes, depth, contextStubTypesEqualToAnything, contextStubTypesNotEqual)
return if (notAllNotNull)
refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.withNullability(true)
else
@@ -90,11 +95,14 @@ object NewCommonSuperTypeCalculator {
}
// Makes representative sample, i.e. (A, B, A) -> (A, B)
private fun TypeSystemCommonSuperTypesContext.uniquify(types: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
private fun TypeSystemCommonSuperTypesContext.uniquify(
types: List<SimpleTypeMarker>,
contextStubTypesNotEqual: AbstractTypeCheckerContext
): List<SimpleTypeMarker> {
val uniqueTypes = arrayListOf<SimpleTypeMarker>()
for (type in types) {
val isNewUniqueType = uniqueTypes.all {
!AbstractTypeChecker.equalTypes(this, it, type, stubTypesEqualToAnything = false) ||
!AbstractTypeChecker.equalTypes(contextStubTypesNotEqual, it, type) ||
it.typeConstructor().isIntegerLiteralTypeConstructor()
}
if (isNewUniqueType) {
@@ -106,15 +114,16 @@ object NewCommonSuperTypeCalculator {
// This function leaves only supertypes, i.e. A0 is a strong supertype for A iff A != A0 && A <: A0
// Explanation: consider types (A : A0, B : B0, A0, B0), then CST(A, B, A0, B0) == CST(CST(A, A0), CST(B, B0)) == CST(A0, B0)
private fun TypeSystemCommonSuperTypesContext.filterSupertypes(list: List<SimpleTypeMarker>): List<SimpleTypeMarker> {
private fun filterSupertypes(
list: List<SimpleTypeMarker>,
contextStubTypesNotEqual: AbstractTypeCheckerContext
): List<SimpleTypeMarker> {
val supertypes = list.toMutableList()
val iterator = supertypes.iterator()
while (iterator.hasNext()) {
val potentialSubtype = iterator.next()
val isSubtype = supertypes.any { supertype ->
supertype !== potentialSubtype && AbstractTypeChecker.isSubtypeOf(
this, potentialSubtype, supertype, stubTypesEqualToAnything = false
)
supertype !== potentialSubtype && AbstractTypeChecker.isSubtypeOf(contextStubTypesNotEqual, potentialSubtype, supertype)
}
if (isSubtype) iterator.remove()
@@ -131,7 +140,9 @@ object NewCommonSuperTypeCalculator {
* */
private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForNotNullTypes(
types: List<SimpleTypeMarker>,
depth: Int
depth: Int,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext,
contextStubTypesNotEqual: AbstractTypeCheckerContext
): SimpleTypeMarker {
if (types.size == 1) return types.single()
@@ -142,16 +153,16 @@ object NewCommonSuperTypeCalculator {
"There should be at least one non-stub type to compute common supertype but there are: $types"
}
val uniqueTypes = uniquify(nonStubTypes)
val uniqueTypes = uniquify(nonStubTypes, contextStubTypesNotEqual)
if (uniqueTypes.size == 1) return uniqueTypes.single()
val explicitSupertypes = filterSupertypes(uniqueTypes)
val explicitSupertypes = filterSupertypes(uniqueTypes, contextStubTypesNotEqual)
if (explicitSupertypes.size == 1) return explicitSupertypes.single()
findErrorTypeInSupertypesIfItIsNeeded(explicitSupertypes)?.let { return it }
findErrorTypeInSupertypesIfItIsNeeded(explicitSupertypes, contextStubTypesEqualToAnything)?.let { return it }
findCommonIntegerLiteralTypesSuperType(explicitSupertypes)?.let { return it }
return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth)
return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth, contextStubTypesEqualToAnything)
}
private fun TypeSystemCommonSuperTypesContext.isStubRelatedType(type: SimpleTypeMarker): Boolean {
@@ -169,27 +180,33 @@ object NewCommonSuperTypeCalculator {
): SimpleTypeMarker? {
if (isErrorTypeAllowed) return null
for (type in types) {
collectAllSupertypes(type).firstOrNull { it.isError() }?.let { return it.toErrorType() }
collectAllSupertypes(type, contextStubTypesEqualToAnything).firstOrNull { it.isError() }?.let { return it.toErrorType() }
}
return null
}
private fun TypeSystemCommonSuperTypesContext.findSuperTypeConstructorsAndIntersectResult(
types: List<SimpleTypeMarker>,
depth: Int
): SimpleTypeMarker {
return intersectTypes(allCommonSuperTypeConstructors(types).map { superTypeWithGivenConstructor(types, it, depth) })
}
depth: Int,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext
): SimpleTypeMarker =
intersectTypes(
allCommonSuperTypeConstructors(types, contextStubTypesEqualToAnything)
.map { superTypeWithGivenConstructor(types, it, depth) }
)
/**
* Note that if there is captured type C, then no one else is not subtype of C => lowerType cannot help here
*/
private fun TypeSystemCommonSuperTypesContext.allCommonSuperTypeConstructors(types: List<SimpleTypeMarker>): List<TypeConstructorMarker> {
val result = collectAllSupertypes(types.first())
private fun TypeSystemCommonSuperTypesContext.allCommonSuperTypeConstructors(
types: List<SimpleTypeMarker>,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext
): List<TypeConstructorMarker> {
val result = collectAllSupertypes(types.first(), contextStubTypesEqualToAnything)
for (type in types) {
if (type === types.first()) continue
result.retainAll(collectAllSupertypes(type))
result.retainAll(collectAllSupertypes(type, contextStubTypesEqualToAnything))
}
return result.filterNot { target ->
result.any { other ->
@@ -198,9 +215,16 @@ object NewCommonSuperTypeCalculator {
}
}
private fun TypeSystemCommonSuperTypesContext.collectAllSupertypes(type: SimpleTypeMarker) =
private fun TypeSystemCommonSuperTypesContext.collectAllSupertypes(
type: SimpleTypeMarker,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext
) =
LinkedHashSet<TypeConstructorMarker>().apply {
type.anySuperTypeConstructor { add(it); false }
contextStubTypesEqualToAnything.anySupertype(
type,
{ add(it.typeConstructor()); false },
{ AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible }
)
}
private fun TypeSystemCommonSuperTypesContext.superTypeWithGivenConstructor(