Clarify naming around inference fork points
^KT-43296 In Progress
This commit is contained in:
committed by
Space Team
parent
715a73c8fb
commit
02b2927921
+1
-2
@@ -62,8 +62,7 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
|
||||
) {
|
||||
val topLevelTypeVariables = topLevelType.extractTypeVariables()
|
||||
|
||||
// NB: it's called in ConstraintSystemForks resolution stage by FE 1.0
|
||||
processForkConstraints()
|
||||
resolveForkPointsConstraints()
|
||||
|
||||
completion@ while (true) {
|
||||
// TODO: This is very slow
|
||||
|
||||
+22
-3
@@ -25,10 +25,29 @@ interface NewConstraintSystem {
|
||||
|
||||
fun asConstraintSystemCompleterContext(): ConstraintSystemCompletionContext
|
||||
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzerContext
|
||||
fun processForkConstraints()
|
||||
fun resolveForkPointsConstraints()
|
||||
|
||||
fun getEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeInfo?
|
||||
}
|
||||
|
||||
typealias ForkPointData = List<ConstraintsFromSingleFork>
|
||||
typealias ConstraintsFromSingleFork = Set<Pair<TypeVariableMarker, Constraint>>
|
||||
/**
|
||||
* In some cases we're not only adding constraints linearly to the system, but sometimes we need to consider several variants of constraints
|
||||
*
|
||||
* For example, from smartcast we've got a value of a type A<Int, String> & A<E, F> that we'd like to pass as an argument to the parameter
|
||||
* of type A<Xv, Yv> (where Xv and Yv are the type variables of the current call)
|
||||
*
|
||||
* So, we've got a subtyping constraint
|
||||
* A<Int, String> & A<E, F> <: A<Xv, Yv>
|
||||
*
|
||||
* And we might go with the first intersection component, having the following variables constraint set: {Xv=Int,Yv=String}
|
||||
* Or, if we'd consider the second component it would be {Xv=E, Yv=F}
|
||||
*
|
||||
* And all existing and future constraints might work differently depending on which option we've chosen.
|
||||
* Thus, ideally we need to create two versions of the constraint system and try to resolve each of them.
|
||||
* But that lead to exponential complexity, so we only use some set of heuristics for that
|
||||
*
|
||||
* Lately, we call such situation a "fork point" and each of the options a "fork point branch"
|
||||
* Each branch is defined by the set of constraints that need to be added to the system if we choose the particular branch.
|
||||
*/
|
||||
typealias ForkPointData = List<ForkPointBranchDescription>
|
||||
typealias ForkPointBranchDescription = Set<Pair<TypeVariableMarker, Constraint>>
|
||||
|
||||
+14
-14
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintsFromSingleFork
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ForkPointBranchDescription
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ForkPointData
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.*
|
||||
@@ -46,7 +46,7 @@ class ConstraintInjector(
|
||||
constraints: MutableList<Pair<TypeVariableMarker, Constraint>>
|
||||
)
|
||||
|
||||
fun processForkConstraints()
|
||||
fun resolveForkPointsConstraints()
|
||||
}
|
||||
|
||||
fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) {
|
||||
@@ -141,7 +141,7 @@ class ConstraintInjector(
|
||||
processConstraints(c, typeCheckerState, skipProperEqualityConstraints = false)
|
||||
}
|
||||
|
||||
fun processForkConstraints(
|
||||
fun processGivenForkPointBranchConstraints(
|
||||
c: Context,
|
||||
constraintSet: Collection<Pair<TypeVariableMarker, Constraint>>,
|
||||
position: IncorporationConstraintPosition
|
||||
@@ -166,7 +166,7 @@ class ConstraintInjector(
|
||||
|
||||
// During completion, we start processing fork constrains immediately
|
||||
if (c.atCompletionState) {
|
||||
c.processForkConstraints()
|
||||
c.resolveForkPointsConstraints()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,8 +275,8 @@ class ConstraintInjector(
|
||||
private var possibleNewConstraints: MutableList<Pair<TypeVariableMarker, Constraint>>? = null
|
||||
|
||||
private var forkPointsData: MutableList<ForkPointData>? = null
|
||||
private var stackForConstraintsSetsFromCurrentForkPoint: Stack<MutableList<ConstraintsFromSingleFork>>? = null
|
||||
private var stackForCurrentConstraintSetFromSingleFork: Stack<MutableList<Pair<TypeVariableMarker, Constraint>>>? = null
|
||||
private var stackForConstraintsSetsFromCurrentForkPoint: Stack<MutableList<ForkPointBranchDescription>>? = null
|
||||
private var stackForConstraintSetFromCurrentForkPointBranch: Stack<MutableList<Pair<TypeVariableMarker, Constraint>>>? = null
|
||||
|
||||
override val isInferenceCompatibilityEnabled = languageVersionSettings.supportsFeature(LanguageFeature.InferenceCompatibility)
|
||||
|
||||
@@ -294,9 +294,9 @@ class ConstraintInjector(
|
||||
fun addPossibleNewConstraint(variable: TypeVariableMarker, constraint: Constraint) {
|
||||
val constraintsSetsFromCurrentFork = stackForConstraintsSetsFromCurrentForkPoint?.lastOrNull()
|
||||
if (constraintsSetsFromCurrentFork != null) {
|
||||
val currentConstraintSetForFork = stackForCurrentConstraintSetFromSingleFork?.lastOrNull()
|
||||
require(currentConstraintSetForFork != null) { "Constraint has been added not under fork {...} call " }
|
||||
currentConstraintSetForFork.add(variable to constraint)
|
||||
val currentConstraintSetForForkPointBranch = stackForConstraintSetFromCurrentForkPointBranch?.lastOrNull()
|
||||
require(currentConstraintSetForForkPointBranch != null) { "Constraint has been added not under fork {...} call " }
|
||||
currentConstraintSetForForkPointBranch.add(variable to constraint)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ class ConstraintInjector(
|
||||
)
|
||||
return true
|
||||
} else if (constraintSets.size == 1) {
|
||||
processForkConstraints(
|
||||
processGivenForkPointBranchConstraints(
|
||||
c,
|
||||
constraintSets.single(),
|
||||
position,
|
||||
@@ -347,17 +347,17 @@ class ConstraintInjector(
|
||||
var anyForkSuccessful = false
|
||||
|
||||
override fun fork(block: () -> Boolean) {
|
||||
if (stackForCurrentConstraintSetFromSingleFork == null) {
|
||||
stackForCurrentConstraintSetFromSingleFork = SmartList()
|
||||
if (stackForConstraintSetFromCurrentForkPointBranch == null) {
|
||||
stackForConstraintSetFromCurrentForkPointBranch = SmartList()
|
||||
}
|
||||
|
||||
stackForCurrentConstraintSetFromSingleFork!!.add(SmartList())
|
||||
stackForConstraintSetFromCurrentForkPointBranch!!.add(SmartList())
|
||||
|
||||
block().also { anyForkSuccessful = anyForkSuccessful || it }
|
||||
|
||||
stackForConstraintsSetsFromCurrentForkPoint!!.last()
|
||||
.addIfNotNull(
|
||||
stackForCurrentConstraintSetFromSingleFork?.popLast()?.takeIf { it.isNotEmpty() }?.toSet()
|
||||
stackForConstraintSetFromCurrentForkPointBranch?.popLast()?.takeIf { it.isNotEmpty() }?.toSet()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedAtomWithRevisableExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
|
||||
abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Context, ResultTypeResolver.Context {
|
||||
abstract val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
|
||||
@@ -33,7 +35,7 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex
|
||||
abstract fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, position: FixVariableConstraintPosition<*>)
|
||||
|
||||
abstract fun couldBeResolvedWithUnrestrictedBuilderInference(): Boolean
|
||||
abstract fun processForkConstraints()
|
||||
abstract fun resolveForkPointsConstraints()
|
||||
|
||||
fun <A : PostponedResolvedAtomMarker> analyzeArgumentWithFixedParameterTypes(
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
|
||||
+12
-8
@@ -357,7 +357,11 @@ class NewConstraintSystemImpl(
|
||||
return storage.constraintsFromAllForkPoints
|
||||
}
|
||||
|
||||
override fun processForkConstraints() {
|
||||
/**
|
||||
* This function tries to find the solution (set of constraints) that is consistent with some branch of each fork
|
||||
* And those constraints are being immediately applied to the system
|
||||
*/
|
||||
override fun resolveForkPointsConstraints() {
|
||||
if (constraintsFromAllForkPoints.isEmpty()) return
|
||||
val allForkPointsData = constraintsFromAllForkPoints.toList()
|
||||
constraintsFromAllForkPoints.clear()
|
||||
@@ -369,7 +373,7 @@ class NewConstraintSystemImpl(
|
||||
// 1. {Xv=Int} – is a one-element set (but potentially there might be more constraints in the set)
|
||||
// 2. {Xv=T} – second constraints set
|
||||
for ((position, forkPointData) in allForkPointsData) {
|
||||
if (!processForkPointData(forkPointData, position)) {
|
||||
if (!applyConstraintsFromFirstSuccessfulBranchOfTheFork(forkPointData, position)) {
|
||||
addError(NoSuccessfulFork(position))
|
||||
}
|
||||
}
|
||||
@@ -392,7 +396,7 @@ class NewConstraintSystemImpl(
|
||||
var result: ConstraintSystemError? = null
|
||||
runTransaction {
|
||||
for ((position, forkPointData) in allForkPointsData) {
|
||||
if (!processForkPointData(forkPointData, position)) {
|
||||
if (!applyConstraintsFromFirstSuccessfulBranchOfTheFork(forkPointData, position)) {
|
||||
result = NoSuccessfulFork(position)
|
||||
break
|
||||
}
|
||||
@@ -409,20 +413,20 @@ class NewConstraintSystemImpl(
|
||||
/**
|
||||
* @return true if there is a successful constraints set for the fork
|
||||
*/
|
||||
private fun processForkPointData(
|
||||
private fun applyConstraintsFromFirstSuccessfulBranchOfTheFork(
|
||||
forkPointData: ForkPointData,
|
||||
position: IncorporationConstraintPosition
|
||||
): Boolean {
|
||||
return forkPointData.any { constraintSetForSingleFork ->
|
||||
return forkPointData.any { constraintSetForForkBranch ->
|
||||
runTransaction {
|
||||
constraintInjector.processForkConstraints(
|
||||
constraintInjector.processGivenForkPointBranchConstraints(
|
||||
this@NewConstraintSystemImpl.apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) },
|
||||
constraintSetForSingleFork,
|
||||
constraintSetForForkBranch,
|
||||
position,
|
||||
)
|
||||
|
||||
if (constraintsFromAllForkPoints.isNotEmpty()) {
|
||||
processForkConstraints()
|
||||
resolveForkPointsConstraints()
|
||||
}
|
||||
|
||||
!hasContradiction
|
||||
|
||||
Reference in New Issue
Block a user