From 6e27d7a2a536f997919e7742677afc96b93feb68 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 27 Nov 2018 13:53:58 +0300 Subject: [PATCH] [NI] Refactor common supertype calculator Make filtration phases more explicit, get rid of `filterNot` --- .../calls/NewCommonSuperTypeCalculator.kt | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 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 5cbc4ff2c48..799370ad982 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt @@ -76,27 +76,45 @@ object NewCommonSuperTypeCalculator { return if (actuallyNotNull) commonSuperType else null } + // Makes representative sample, i.e. (A, B, A) -> (A, B) private fun List.uniquify(): List { - val result = ArrayList() + val uniqueTypes = arrayListOf() for (type in this) { - if (!result.any { NewKotlinTypeChecker.equalTypes(it, type) }) { - result.add(type) + val isNewUniqueType = uniqueTypes.all { !NewKotlinTypeChecker.equalTypes(it, type) } + if (isNewUniqueType) { + uniqueTypes += type } } - return result + return uniqueTypes + } + + // 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 List.filterSupertypes(): List { + val supertypes = this.toMutableList() + val iterator = supertypes.iterator() + while (iterator.hasNext()) { + val potentialSubtype = iterator.next() + val isSubtype = supertypes.any { supertype -> + supertype !== potentialSubtype && NewKotlinTypeChecker.isSubtypeOf(potentialSubtype, supertype) + } + + if (isSubtype) iterator.remove() + } + + return supertypes } private fun commonSuperTypeForNotNullTypes(types: List, depth: Int): SimpleType { + if (types.size == 1) return types.single() + val uniqueTypes = types.uniquify() - val filteredType = uniqueTypes.filterNot { type -> - uniqueTypes.any { other -> type != other && NewKotlinTypeChecker.isSubtypeOf(type, other) } - } - // seems like all types are equal - if (filteredType.isEmpty()) return uniqueTypes.first() + if (uniqueTypes.size == 1) return uniqueTypes.single() - filteredType.singleOrNull()?.let { return it } + val explicitSupertypes = uniqueTypes.filterSupertypes() + if (explicitSupertypes.size == 1) return explicitSupertypes.single() - return findSuperTypeConstructorsAndIntersectResult(filteredType, depth) + return findSuperTypeConstructorsAndIntersectResult(explicitSupertypes, depth) } private fun findSuperTypeConstructorsAndIntersectResult(types: List, depth: Int): SimpleType {