[FE] Cache checking intersection type emptiness results
This commit is contained in:
committed by
teamcity
parent
9a3b5e547b
commit
e133ee3765
@@ -584,7 +584,7 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
|
|||||||
if (upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() })
|
if (upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() })
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
if (candidate.system.getEmptyIntersectionTypeKind(upperTypes).isDefinitelyEmpty()) {
|
||||||
sink.yieldDiagnostic(
|
sink.yieldDiagnostic(
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
InferredEmptyIntersectionDiagnostic(
|
InferredEmptyIntersectionDiagnostic(
|
||||||
|
|||||||
+4
@@ -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.Constraint
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
|
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
|
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||||
|
|
||||||
interface NewConstraintSystem {
|
interface NewConstraintSystem {
|
||||||
@@ -24,6 +26,8 @@ interface NewConstraintSystem {
|
|||||||
fun asConstraintSystemCompleterContext(): ConstraintSystemCompletionContext
|
fun asConstraintSystemCompleterContext(): ConstraintSystemCompletionContext
|
||||||
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzerContext
|
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzerContext
|
||||||
fun processForkConstraints()
|
fun processForkConstraints()
|
||||||
|
|
||||||
|
fun getEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeKind
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias ForkPointData = List<ConstraintsFromSingleFork>
|
typealias ForkPointData = List<ConstraintsFromSingleFork>
|
||||||
|
|||||||
+19
-5
@@ -10,10 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|||||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.*
|
import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
|
||||||
import org.jetbrains.kotlin.types.isDefinitelyEmpty
|
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
@@ -41,6 +38,8 @@ class NewConstraintSystemImpl(
|
|||||||
private val typeVariablesTransaction: MutableList<TypeVariableMarker> = SmartList()
|
private val typeVariablesTransaction: MutableList<TypeVariableMarker> = SmartList()
|
||||||
private val properTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
private val properTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
||||||
private val notProperTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
private val notProperTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
||||||
|
private val emptyIntersectionTypesCache: MutableSet<Collection<KotlinTypeMarker>> = SmartSet.create()
|
||||||
|
private val nonEmptyIntersectionTypesCache: MutableSet<Collection<KotlinTypeMarker>> = SmartSet.create()
|
||||||
|
|
||||||
private var couldBeResolvedWithUnrestrictedBuilderInference: Boolean = false
|
private var couldBeResolvedWithUnrestrictedBuilderInference: Boolean = false
|
||||||
|
|
||||||
@@ -444,6 +443,21 @@ class NewConstraintSystemImpl(
|
|||||||
doPostponedComputationsIfAllVariablesAreFixed()
|
doPostponedComputationsIfAllVariablesAreFixed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): 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) {
|
private fun checkInferredEmptyIntersection(variable: TypeVariableMarker, resultType: KotlinTypeMarker) {
|
||||||
val intersectionTypeConstructor = resultType.typeConstructor().takeIf { it is IntersectionTypeConstructorMarker } ?: return
|
val intersectionTypeConstructor = resultType.typeConstructor().takeIf { it is IntersectionTypeConstructorMarker } ?: return
|
||||||
val isInferredEmptyIntersectionForbidden =
|
val isInferredEmptyIntersectionForbidden =
|
||||||
@@ -454,7 +468,7 @@ class NewConstraintSystemImpl(
|
|||||||
if (upperTypes.size <= 1 || storage.errors.any { it is InferredEmptyIntersection && it.incompatibleTypes == upperTypes })
|
if (upperTypes.size <= 1 || storage.errors.any { it is InferredEmptyIntersection && it.incompatibleTypes == upperTypes })
|
||||||
return
|
return
|
||||||
|
|
||||||
if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) {
|
if (getEmptyIntersectionTypeKind(upperTypes).isDefinitelyEmpty()) {
|
||||||
// Remove existing errors from resolution stage because a completion error is more precise
|
// Remove existing errors from resolution stage because a completion error is more precise
|
||||||
storage.errors.removeIf { it is InferredEmptyIntersection }
|
storage.errors.removeIf { it is InferredEmptyIntersection }
|
||||||
val errorFactory =
|
val errorFactory =
|
||||||
|
|||||||
+3
-2
@@ -889,7 +889,8 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() {
|
|||||||
callComponents.statelessCallbacks.isOldIntersectionIsEmpty(upperTypes.cast())
|
callComponents.statelessCallbacks.isOldIntersectionIsEmpty(upperTypes.cast())
|
||||||
|
|
||||||
override fun ResolutionCandidate.process(workIndex: Int) = with(getSystem().asConstraintSystemCompleterContext()) {
|
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()
|
val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness()
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@@ -900,7 +901,7 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() {
|
|||||||
markCandidateForCompatibilityResolve(needToReportWarning = false)
|
markCandidateForCompatibilityResolve(needToReportWarning = false)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty() -> {
|
constraintSystem.getEmptyIntersectionTypeKind(upperTypes).isDefinitelyEmpty() -> {
|
||||||
val isInferredEmptyIntersectionForbidden =
|
val isInferredEmptyIntersectionForbidden =
|
||||||
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
|
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user