NI: do explicit incorporation of type of fixing type variable into other constraints

^KT-37380 Fixed
This commit is contained in:
Victor Petukhov
2020-05-26 22:44:10 +03:00
parent 3643b7b0ca
commit d7f52e8b67
3 changed files with 36 additions and 8 deletions
@@ -38,6 +38,9 @@ class ConstraintIncorporator(
fun addNewIncorporatedConstraint(typeVariable: TypeVariableMarker, type: KotlinTypeMarker, constraintContext: ConstraintContext)
}
fun incorporateIntoOtherConstraints(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) =
c.insideOtherConstraint(typeVariable, constraint)
// \alpha is typeVariable, \beta -- other type variable registered in ConstraintStorage
fun incorporate(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) {
// we shouldn't incorporate recursive constraint -- It is too dangerous
@@ -19,8 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.LOWER
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.UPPER
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.*
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
@@ -56,7 +55,7 @@ class ConstraintInjector(
}
fun addInitialEqualityConstraint(c: Context, a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) {
val initialConstraint = InitialConstraint(a, b, ConstraintKind.EQUALITY, position)
val initialConstraint = InitialConstraint(a, b, EQUALITY, position)
c.addInitialConstraint(initialConstraint)
updateAllowedTypeDepth(c, a)
updateAllowedTypeDepth(c, b)
@@ -81,8 +80,11 @@ class ConstraintInjector(
typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
var constraintsFromIsSubtype = true
while (possibleNewConstraints != null) {
if (incorporatePosition.from is FixVariableConstraintPosition && lowerType == incorporatePosition.initialConstraint.a) {
c.incorporateEqualityConstraintForFixingTypeVariable(incorporatePosition, typeCheckerContext)
}
while (possibleNewConstraints != null) {
val constraintsToProcess = possibleNewConstraints
possibleNewConstraints = null
for ((typeVariable, constraint) in constraintsToProcess!!) {
@@ -103,7 +105,7 @@ class ConstraintInjector(
if (possibleNewConstraints == null ||
(contextOps != null && c.notFixedTypeVariables.all { typeVariable ->
typeVariable.value.constraints.any { constraint ->
constraint.kind == ConstraintKind.EQUALITY && contextOps.isProperType(constraint.type)
constraint.kind == EQUALITY && contextOps.isProperType(constraint.type)
}
})
) {
@@ -117,6 +119,29 @@ class ConstraintInjector(
c.maxTypeDepthFromInitialConstraints = max(c.maxTypeDepthFromInitialConstraints, initialType.typeDepth())
}
private fun Context.incorporateEqualityConstraintForFixingTypeVariable(
incorporatePosition: IncorporationConstraintPosition,
typeCheckerContext: TypeCheckerContext
) {
if (incorporatePosition.from !is FixVariableConstraintPosition) return
val typeToIncorporate = incorporatePosition.initialConstraint.b
if (typeToIncorporate.isUninferredParameter() || typeToIncorporate.isError()) return
constraintIncorporator.incorporateIntoOtherConstraints(
typeCheckerContext,
incorporatePosition.from.variable,
Constraint(
EQUALITY,
typeToIncorporate,
incorporatePosition,
derivedFrom = setOf(),
isNullabilityConstraint = false
)
)
}
private fun Context.shouldWeSkipConstraint(
typeVariable: TypeVariableMarker,
constraint: Constraint,
@@ -30,7 +30,7 @@ class Foo<out A> {
other1.product(
other2.product(
other3.product(
<!TYPE_MISMATCH!>bar { d -> { c -> { b -> { a -> function(<!DEBUG_INFO_EXPRESSION_TYPE("A")!>a<!>, <!DEBUG_INFO_EXPRESSION_TYPE("B")!>b<!>, <!DEBUG_INFO_EXPRESSION_TYPE("C")!>c<!>, <!DEBUG_INFO_EXPRESSION_TYPE("D")!>d<!>) } } } }<!>
bar { d -> { c -> { b -> { a -> function(<!DEBUG_INFO_EXPRESSION_TYPE("A")!>a<!>, <!DEBUG_INFO_EXPRESSION_TYPE("B")!>b<!>, <!DEBUG_INFO_EXPRESSION_TYPE("C")!>c<!>, <!DEBUG_INFO_EXPRESSION_TYPE("D")!>d<!>) } } } }
)
)
)
@@ -43,9 +43,9 @@ class Foo<out A> {
other1.product(
other2.product(
other3.product(
<!TYPE_MISMATCH!>other4.product(
other4.product(
bar { e -> { d -> { c -> { b -> { a -> function(<!DEBUG_INFO_EXPRESSION_TYPE("A")!>a<!>, <!DEBUG_INFO_EXPRESSION_TYPE("B")!>b<!>, <!DEBUG_INFO_EXPRESSION_TYPE("C")!>c<!>, <!DEBUG_INFO_EXPRESSION_TYPE("D")!>d<!>, <!DEBUG_INFO_EXPRESSION_TYPE("E")!>e<!>) } } } } }
)<!>
)
)
)
)