[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.*
|
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(
|
||||||
|
|||||||
Reference in New Issue
Block a user