From 4d01ad439a8549409d9b5dc72433090d7027fc7f Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 24 Nov 2022 18:19:35 +0100 Subject: [PATCH] EmptyIntersectionTypeChecker: simplify code --- .../checkers/EmptyIntersectionTypeChecker.kt | 47 ++++++++----------- .../kotlin/types/EmptyIntersectionTypeKind.kt | 6 +-- 2 files changed, 22 insertions(+), 31 deletions(-) diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt index 1768d943a70..34c8a6a5a03 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.EmptyIntersectionTypeKind import org.jetbrains.kotlin.types.isDefinitelyEmpty import org.jetbrains.kotlin.types.isPossiblyEmpty +import org.jetbrains.kotlin.types.TypeCheckerState import org.jetbrains.kotlin.types.model.* internal object EmptyIntersectionTypeChecker { @@ -91,39 +92,24 @@ internal object EmptyIntersectionTypeChecker { return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.MULTIPLE_CLASSES, firstType, secondType) } - val atLeastOneInterface = firstTypeConstructor.isInterface() || secondTypeConstructor.isInterface() - if (atLeastOneInterface) { - val incompatibleSupertypes = getIncompatibleSuperTypes(firstType, secondType) - if (incompatibleSupertypes != null) { - return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.INCOMPATIBLE_SUPERTYPES, *incompatibleSupertypes) - } - } - - val firstSuperTypeWithSecondConstructor = AbstractTypeChecker.findCorrespondingSupertypes( - typeCheckerState, firstType.lowerBoundIfFlexible(), secondTypeConstructor - ).singleOrNull() - val secondSuperTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes( - typeCheckerState, secondType.lowerBoundIfFlexible(), firstTypeConstructor - ).singleOrNull() - when { - firstSuperTypeWithSecondConstructor != null || secondSuperTypeByFirstConstructor != null -> { - continue + firstType.lowerBoundIfFlexible().isSubtypeOfIgnoringArguments(typeCheckerState, secondTypeConstructor) || + secondType.lowerBoundIfFlexible().isSubtypeOfIgnoringArguments(typeCheckerState, firstTypeConstructor) -> { } - !atLeastOneInterface -> { + !firstTypeConstructor.isInterface() && !secondTypeConstructor.isInterface() -> { // Two classes can't have a common subtype if neither is a subtype of another return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.MULTIPLE_CLASSES, firstType, secondType) } - else -> { - // don't have incompatible supertypes so can have a common subtype only if all types are interfaces - if (firstTypeConstructor.isFinalClassConstructor() || secondTypeConstructor.isFinalClassConstructor()) { - possibleEmptyIntersectionKind = EmptyIntersectionTypeInfo( - if (atLeastOneInterface) EmptyIntersectionTypeKind.FINAL_CLASS_AND_INTERFACE - else EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS, - firstType, secondType - ) + firstTypeConstructor.isFinalClassConstructor() || secondTypeConstructor.isFinalClassConstructor() -> { + val incompatibleSupertypes = getIncompatibleSuperTypes(firstType, secondType) + if (incompatibleSupertypes != null) { + return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.INCOMPATIBLE_SUPERTYPES, *incompatibleSupertypes) } - continue + // don't have incompatible supertypes so can have a common subtype only if all types are interfaces + possibleEmptyIntersectionKind = EmptyIntersectionTypeInfo( + EmptyIntersectionTypeKind.FINAL_CLASS_AND_INTERFACE, + firstType, secondType + ) } } } @@ -132,6 +118,13 @@ internal object EmptyIntersectionTypeChecker { return possibleEmptyIntersectionKind } + private fun SimpleTypeMarker.isSubtypeOfIgnoringArguments( + typeCheckerState: TypeCheckerState, + otherConstructorMarker: TypeConstructorMarker + ): Boolean = AbstractTypeChecker.findCorrespondingSupertypes( + typeCheckerState, this, otherConstructorMarker + ).isNotEmpty() + private fun TypeSystemInferenceExtensionContext.getIncompatibleSuperTypes( firstType: KotlinTypeMarker, secondType: KotlinTypeMarker ): Array? { diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt index 09a412b445a..cc0e2e451bf 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt @@ -9,8 +9,7 @@ enum class EmptyIntersectionTypeKind(val description: String) { MULTIPLE_CLASSES("multiple incompatible classes"), INCOMPATIBLE_SUPERTYPES("incompatible supertypes"), INCOMPATIBLE_TYPE_ARGUMENTS("incompatible type arguments"), - FINAL_CLASS_AND_INTERFACE("final class and interface"), - SINGLE_FINAL_CLASS("final class and non-final class") + FINAL_CLASS_AND_INTERFACE("final class and interface") } fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean = @@ -18,5 +17,4 @@ fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean = || this == EmptyIntersectionTypeKind.INCOMPATIBLE_SUPERTYPES || this == EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS -fun EmptyIntersectionTypeKind.isPossiblyEmpty(): Boolean = - this == EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS || this == EmptyIntersectionTypeKind.FINAL_CLASS_AND_INTERFACE +fun EmptyIntersectionTypeKind.isPossiblyEmpty(): Boolean = this == EmptyIntersectionTypeKind.FINAL_CLASS_AND_INTERFACE