[NI] Don't recreate subtyping context every time
This commit is contained in:
+51
-27
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user