[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.* import org.jetbrains.kotlin.types.model.*
object NewCommonSuperTypeCalculator { object NewCommonSuperTypeCalculator {
// TODO: Bridge for old calls // TODO: Bridge for old calls
fun commonSuperType(types: List<UnwrappedType>): UnwrappedType { fun commonSuperType(types: List<UnwrappedType>): UnwrappedType {
return SimpleClassicTypeSystemContext.commonSuperType(types) as 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 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) return createFlexibleType(lowerSuperType, upperSuperType)
} }
private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForSimpleTypes( private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForSimpleTypes(
types: List<SimpleTypeMarker>, types: List<SimpleTypeMarker>,
depth: Int depth: Int,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext,
contextStubTypesNotEqual: AbstractTypeCheckerContext
): SimpleTypeMarker { ): SimpleTypeMarker {
// i.e. result type also should be marked nullable // i.e. result type also should be marked nullable
val notAllNotNull = val notAllNotNull =
types.any { !isStubRelatedType(it) && !AbstractNullabilityChecker.isSubtypeOfAny(contextStubTypesEqualToAnything, it) } types.any { !isStubRelatedType(it) && !AbstractNullabilityChecker.isSubtypeOfAny(contextStubTypesEqualToAnything, it) }
val notNullTypes = if (notAllNotNull) types.map { it.withNullability(false) } else types 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) return if (notAllNotNull)
refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.withNullability(true) refineNullabilityForUndefinedNullability(types, commonSuperType) ?: commonSuperType.withNullability(true)
else else
@@ -90,11 +95,14 @@ object NewCommonSuperTypeCalculator {
} }
// Makes representative sample, i.e. (A, B, A) -> (A, B) // 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>() val uniqueTypes = arrayListOf<SimpleTypeMarker>()
for (type in types) { for (type in types) {
val isNewUniqueType = uniqueTypes.all { val isNewUniqueType = uniqueTypes.all {
!AbstractTypeChecker.equalTypes(this, it, type, stubTypesEqualToAnything = false) || !AbstractTypeChecker.equalTypes(contextStubTypesNotEqual, it, type) ||
it.typeConstructor().isIntegerLiteralTypeConstructor() it.typeConstructor().isIntegerLiteralTypeConstructor()
} }
if (isNewUniqueType) { 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 // 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) // 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 supertypes = list.toMutableList()
val iterator = supertypes.iterator() val iterator = supertypes.iterator()
while (iterator.hasNext()) { while (iterator.hasNext()) {
val potentialSubtype = iterator.next() val potentialSubtype = iterator.next()
val isSubtype = supertypes.any { supertype -> val isSubtype = supertypes.any { supertype ->
supertype !== potentialSubtype && AbstractTypeChecker.isSubtypeOf( supertype !== potentialSubtype && AbstractTypeChecker.isSubtypeOf(contextStubTypesNotEqual, potentialSubtype, supertype)
this, potentialSubtype, supertype, stubTypesEqualToAnything = false
)
} }
if (isSubtype) iterator.remove() if (isSubtype) iterator.remove()
@@ -131,7 +140,9 @@ object NewCommonSuperTypeCalculator {
* */ * */
private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForNotNullTypes( private fun TypeSystemCommonSuperTypesContext.commonSuperTypeForNotNullTypes(
types: List<SimpleTypeMarker>, types: List<SimpleTypeMarker>,
depth: Int depth: Int,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext,
contextStubTypesNotEqual: AbstractTypeCheckerContext
): SimpleTypeMarker { ): SimpleTypeMarker {
if (types.size == 1) return types.single() 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" "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() if (uniqueTypes.size == 1) return uniqueTypes.single()
val explicitSupertypes = filterSupertypes(uniqueTypes) val explicitSupertypes = filterSupertypes(uniqueTypes, contextStubTypesNotEqual)
if (explicitSupertypes.size == 1) return explicitSupertypes.single() if (explicitSupertypes.size == 1) return explicitSupertypes.single()
findErrorTypeInSupertypesIfItIsNeeded(explicitSupertypes)?.let { return it } findErrorTypeInSupertypesIfItIsNeeded(explicitSupertypes, contextStubTypesEqualToAnything)?.let { return it }
findCommonIntegerLiteralTypesSuperType(explicitSupertypes)?.let { return it } findCommonIntegerLiteralTypesSuperType(explicitSupertypes)?.let { return it }
return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth) return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth, contextStubTypesEqualToAnything)
} }
private fun TypeSystemCommonSuperTypesContext.isStubRelatedType(type: SimpleTypeMarker): Boolean { private fun TypeSystemCommonSuperTypesContext.isStubRelatedType(type: SimpleTypeMarker): Boolean {
@@ -169,27 +180,33 @@ object NewCommonSuperTypeCalculator {
): SimpleTypeMarker? { ): SimpleTypeMarker? {
if (isErrorTypeAllowed) return null if (isErrorTypeAllowed) return null
for (type in types) { 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 return null
} }
private fun TypeSystemCommonSuperTypesContext.findSuperTypeConstructorsAndIntersectResult( private fun TypeSystemCommonSuperTypesContext.findSuperTypeConstructorsAndIntersectResult(
types: List<SimpleTypeMarker>, types: List<SimpleTypeMarker>,
depth: Int depth: Int,
): SimpleTypeMarker { contextStubTypesEqualToAnything: AbstractTypeCheckerContext
return intersectTypes(allCommonSuperTypeConstructors(types).map { superTypeWithGivenConstructor(types, it, depth) }) ): 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 * 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> { private fun TypeSystemCommonSuperTypesContext.allCommonSuperTypeConstructors(
val result = collectAllSupertypes(types.first()) types: List<SimpleTypeMarker>,
contextStubTypesEqualToAnything: AbstractTypeCheckerContext
): List<TypeConstructorMarker> {
val result = collectAllSupertypes(types.first(), contextStubTypesEqualToAnything)
for (type in types) { for (type in types) {
if (type === types.first()) continue if (type === types.first()) continue
result.retainAll(collectAllSupertypes(type)) result.retainAll(collectAllSupertypes(type, contextStubTypesEqualToAnything))
} }
return result.filterNot { target -> return result.filterNot { target ->
result.any { other -> 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 { LinkedHashSet<TypeConstructorMarker>().apply {
type.anySuperTypeConstructor { add(it); false } contextStubTypesEqualToAnything.anySupertype(
type,
{ add(it.typeConstructor()); false },
{ AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible }
)
} }
private fun TypeSystemCommonSuperTypesContext.superTypeWithGivenConstructor( private fun TypeSystemCommonSuperTypesContext.superTypeWithGivenConstructor(