From e8907c078d88063dbdbb7171ef1acc5e5258861f Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 13 Sep 2019 12:55:53 +0300 Subject: [PATCH] [NI] Don't recreate subtyping context every time --- .../calls/NewCommonSuperTypeCalculator.kt | 78 ++++++++++++------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt index 708b0ae37c2..2ed6549be83 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt @@ -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 { 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, - 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): List { + private fun TypeSystemCommonSuperTypesContext.uniquify( + types: List, + contextStubTypesNotEqual: AbstractTypeCheckerContext + ): List { val uniqueTypes = arrayListOf() 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): List { + private fun filterSupertypes( + list: List, + contextStubTypesNotEqual: AbstractTypeCheckerContext + ): List { 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, - 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, - 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): List { - val result = collectAllSupertypes(types.first()) + private fun TypeSystemCommonSuperTypesContext.allCommonSuperTypeConstructors( + types: List, + contextStubTypesEqualToAnything: AbstractTypeCheckerContext + ): List { + 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().apply { - type.anySuperTypeConstructor { add(it); false } + contextStubTypesEqualToAnything.anySupertype( + type, + { add(it.typeConstructor()); false }, + { AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible } + ) } private fun TypeSystemCommonSuperTypesContext.superTypeWithGivenConstructor(