diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index ec23f7e68ed..9968f8e08fb 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -584,7 +584,7 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() { if (upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() }) continue - if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) { + if (candidate.system.getEmptyIntersectionTypeKind(upperTypes).isDefinitelyEmpty()) { sink.yieldDiagnostic( @Suppress("UNCHECKED_CAST") InferredEmptyIntersectionDiagnostic( diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt index 11e2aead7dd..9af06743a10 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt @@ -10,6 +10,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemC import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError +import org.jetbrains.kotlin.types.EmptyIntersectionTypeKind +import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeVariableMarker interface NewConstraintSystem { @@ -24,6 +26,8 @@ interface NewConstraintSystem { fun asConstraintSystemCompleterContext(): ConstraintSystemCompletionContext fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzerContext fun processForkConstraints() + + fun getEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeKind } typealias ForkPointData = List diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index eb57f3fdd62..e9956094f3d 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -10,10 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext import org.jetbrains.kotlin.resolve.calls.inference.* import org.jetbrains.kotlin.resolve.calls.inference.components.* -import org.jetbrains.kotlin.types.AbstractTypeApproximator -import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.types.TypeApproximatorConfiguration -import org.jetbrains.kotlin.types.isDefinitelyEmpty +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartSet @@ -41,6 +38,8 @@ class NewConstraintSystemImpl( private val typeVariablesTransaction: MutableList = SmartList() private val properTypesCache: MutableSet = SmartSet.create() private val notProperTypesCache: MutableSet = SmartSet.create() + private val emptyIntersectionTypesCache: MutableSet> = SmartSet.create() + private val nonEmptyIntersectionTypesCache: MutableSet> = SmartSet.create() private var couldBeResolvedWithUnrestrictedBuilderInference: Boolean = false @@ -444,6 +443,21 @@ class NewConstraintSystemImpl( doPostponedComputationsIfAllVariablesAreFixed() } + override fun getEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeKind { + if (types in emptyIntersectionTypesCache) + return EmptyIntersectionTypeKind.MULTIPLE_CLASSES + + if (types in nonEmptyIntersectionTypesCache) + return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION + + return types.computeEmptyIntersectionTypeKind().also { + when (it) { + EmptyIntersectionTypeKind.MULTIPLE_CLASSES -> emptyIntersectionTypesCache.add(types) + EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION -> nonEmptyIntersectionTypesCache.add(types) + } + } + } + private fun checkInferredEmptyIntersection(variable: TypeVariableMarker, resultType: KotlinTypeMarker) { val intersectionTypeConstructor = resultType.typeConstructor().takeIf { it is IntersectionTypeConstructorMarker } ?: return val isInferredEmptyIntersectionForbidden = @@ -454,7 +468,7 @@ class NewConstraintSystemImpl( if (upperTypes.size <= 1 || storage.errors.any { it is InferredEmptyIntersection && it.incompatibleTypes == upperTypes }) return - if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) { + if (getEmptyIntersectionTypeKind(upperTypes).isDefinitelyEmpty()) { // Remove existing errors from resolution stage because a completion error is more precise storage.errors.removeIf { it is InferredEmptyIntersection } val errorFactory = diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index 0e01f41f3f3..29ed8e1fe83 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -889,7 +889,8 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() { callComponents.statelessCallbacks.isOldIntersectionIsEmpty(upperTypes.cast()) override fun ResolutionCandidate.process(workIndex: Int) = with(getSystem().asConstraintSystemCompleterContext()) { - for (variableWithConstraints in getSystem().getBuilder().currentStorage().notFixedTypeVariables.values) { + val constraintSystem = getSystem() + for (variableWithConstraints in constraintSystem.getBuilder().currentStorage().notFixedTypeVariables.values) { val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness() when { @@ -900,7 +901,7 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() { markCandidateForCompatibilityResolve(needToReportWarning = false) continue } - upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty() -> { + constraintSystem.getEmptyIntersectionTypeKind(upperTypes).isDefinitelyEmpty() -> { val isInferredEmptyIntersectionForbidden = callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)