[NI] Support fixation to subtype in completion mode calculator
Allow full compltion mode for return type depending on type parameters in contravariant position only if they have proper equality constraint.
This commit is contained in:
+12
-11
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
|
||||
import java.util.*
|
||||
|
||||
typealias CsCompleterContext = KotlinConstraintSystemCompleter.Context
|
||||
@@ -45,10 +46,11 @@ class CompletionModeCalculator {
|
||||
private val csCompleterContext: CsCompleterContext
|
||||
) {
|
||||
private enum class FixationDirection {
|
||||
TO_SUBTYPE, TO_SUPERTYPE, EQUALITY
|
||||
TO_SUBTYPE, EQUALITY
|
||||
}
|
||||
|
||||
private val fixationDirectionsForVariables = mutableMapOf<VariableWithConstraints, FixationDirection>()
|
||||
private val fixationDirectionsForVariables: MutableMap<VariableWithConstraints, FixationDirection> =
|
||||
newLinkedHashMapWithExpectedSize(csCompleterContext.notFixedTypeVariables.size)
|
||||
private val variablesWithQueuedConstraints = mutableSetOf<TypeVariableMarker>()
|
||||
private val typesToProcess: Queue<KotlinTypeMarker> = ArrayDeque()
|
||||
|
||||
@@ -68,14 +70,14 @@ class CompletionModeCalculator {
|
||||
while (typesToProcess.isNotEmpty()) {
|
||||
val type = typesToProcess.poll() ?: break
|
||||
|
||||
fixationRequirementForTopLevel(type)?.let { directionForVariable ->
|
||||
fixationDirectionForTopLevel(type)?.let { directionForVariable ->
|
||||
updateDirection(directionForVariable)
|
||||
enqueueTypesFromConstraints(directionForVariable.variable)
|
||||
}
|
||||
|
||||
// find all variables in type and make requirements for them
|
||||
type.contains { fromReturnType ->
|
||||
for (directionForVariable in directionsForVariablesInTypeArguments(fromReturnType)) {
|
||||
type.contains { typePart ->
|
||||
for (directionForVariable in directionsForVariablesInTypeArguments(typePart)) {
|
||||
updateDirection(directionForVariable)
|
||||
enqueueTypesFromConstraints(directionForVariable.variable)
|
||||
}
|
||||
@@ -106,16 +108,16 @@ class CompletionModeCalculator {
|
||||
private fun updateDirection(directionForVariable: FixationDirectionForVariable) {
|
||||
val (variable, newDirection) = directionForVariable
|
||||
fixationDirectionsForVariables[variable]?.let { oldDirection ->
|
||||
// To sub and to super are merged into equality, old equality stays
|
||||
if (oldDirection != FixationDirection.EQUALITY && oldDirection != newDirection)
|
||||
fixationDirectionsForVariables[variable] = FixationDirection.EQUALITY
|
||||
} ?: run {
|
||||
fixationDirectionsForVariables[variable] = newDirection
|
||||
}
|
||||
fixationDirectionsForVariables[variable] = newDirection
|
||||
}
|
||||
|
||||
private data class FixationDirectionForVariable(val variable: VariableWithConstraints, val direction: FixationDirection)
|
||||
|
||||
private fun CsCompleterContext.fixationRequirementForTopLevel(type: KotlinTypeMarker): FixationDirectionForVariable? {
|
||||
private fun CsCompleterContext.fixationDirectionForTopLevel(type: KotlinTypeMarker): FixationDirectionForVariable? {
|
||||
return notFixedTypeVariables[type.typeConstructor()]?.let {
|
||||
FixationDirectionForVariable(it, FixationDirection.TO_SUBTYPE)
|
||||
}
|
||||
@@ -138,10 +140,10 @@ class CompletionModeCalculator {
|
||||
|
||||
val parameter = type.typeConstructor().getParameter(position)
|
||||
val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
||||
?: TypeVariance.OUT // Discuss
|
||||
?: TypeVariance.INV
|
||||
|
||||
val direction = when (effectiveVariance) {
|
||||
TypeVariance.IN -> FixationDirection.TO_SUPERTYPE
|
||||
TypeVariance.IN -> FixationDirection.EQUALITY // Assuming that variables in contravariant positions are fixed to subtype
|
||||
TypeVariance.OUT -> FixationDirection.TO_SUBTYPE
|
||||
TypeVariance.INV -> FixationDirection.EQUALITY
|
||||
}
|
||||
@@ -169,7 +171,6 @@ class CompletionModeCalculator {
|
||||
|
||||
private fun Constraint.hasRequiredKind(direction: FixationDirection) = when (direction) {
|
||||
FixationDirection.TO_SUBTYPE -> kind.isLower() || kind.isEqual()
|
||||
FixationDirection.TO_SUPERTYPE -> kind.isUpper() || kind.isEqual()
|
||||
FixationDirection.EQUALITY -> kind.isEqual()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user