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 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 // \alpha is typeVariable, \beta -- other type variable registered in ConstraintStorage
fun incorporate(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) { fun incorporate(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) {
// we shouldn't incorporate recursive constraint -- It is too dangerous // 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.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.* 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.*
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.UPPER
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
@@ -56,7 +55,7 @@ class ConstraintInjector(
} }
fun addInitialEqualityConstraint(c: Context, a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) { 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) c.addInitialConstraint(initialConstraint)
updateAllowedTypeDepth(c, a) updateAllowedTypeDepth(c, a)
updateAllowedTypeDepth(c, b) updateAllowedTypeDepth(c, b)
@@ -81,8 +80,11 @@ class ConstraintInjector(
typeCheckerContext.runIsSubtypeOf(lowerType, upperType) typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
var constraintsFromIsSubtype = true 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 val constraintsToProcess = possibleNewConstraints
possibleNewConstraints = null possibleNewConstraints = null
for ((typeVariable, constraint) in constraintsToProcess!!) { for ((typeVariable, constraint) in constraintsToProcess!!) {
@@ -103,7 +105,7 @@ class ConstraintInjector(
if (possibleNewConstraints == null || if (possibleNewConstraints == null ||
(contextOps != null && c.notFixedTypeVariables.all { typeVariable -> (contextOps != null && c.notFixedTypeVariables.all { typeVariable ->
typeVariable.value.constraints.any { constraint -> 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()) 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( private fun Context.shouldWeSkipConstraint(
typeVariable: TypeVariableMarker, typeVariable: TypeVariableMarker,
constraint: Constraint, constraint: Constraint,
@@ -30,7 +30,7 @@ class Foo<out A> {
other1.product( other1.product(
other2.product( other2.product(
other3.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( other1.product(
other2.product( other2.product(
other3.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<!>) } } } } } 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<!>) } } } } }
)<!> )
) )
) )
) )