KT-8879 Stackoverflow exception on completion from inference
#KT-8879 Fixed Added ConstraintContext storing 'derivedFrom' variables. This information is used to prevent infinite recursion: if a variable was substituted in a type of a bound, it shouldn't be substituted there for the second time.
This commit is contained in:
@@ -6,6 +6,7 @@ interface C : B
|
|||||||
|
|
||||||
interface Consumer<in T>
|
interface Consumer<in T>
|
||||||
interface Producer<out T>
|
interface Producer<out T>
|
||||||
|
interface Inv<T>
|
||||||
|
|
||||||
interface My<T>
|
interface My<T>
|
||||||
interface Successor<T> : My<T>
|
interface Successor<T> : My<T>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
VARIABLES T P
|
||||||
|
|
||||||
|
T <: My<T>
|
||||||
|
Inv<P> <: Inv<T>
|
||||||
|
|
||||||
|
type parameter bounds:
|
||||||
|
T <: My<T>*, := P*, <: My<out My<T>>*, <: My<P>*, <: My<out My<P>>*, <: My<out My<out My<T>>>*
|
||||||
|
P := T*, <: My<T>*, <: My<out My<T>>*, <: My<P>*, <: My<out My<P>>*, <: My<out My<out My<T>>>*
|
||||||
|
|
||||||
|
status:
|
||||||
|
-hasCannotCaptureTypesError: false
|
||||||
|
-hasConflictingConstraints: false
|
||||||
|
-hasContradiction: false
|
||||||
|
-hasErrorInConstrainingTypes: false
|
||||||
|
-hasParameterConstraintError: false
|
||||||
|
-hasTypeInferenceIncorporationError: false
|
||||||
|
-hasUnknownParameters: true
|
||||||
|
-hasViolatedUpperBound: false
|
||||||
|
-isSuccessful: false
|
||||||
|
|
||||||
|
result:
|
||||||
|
T=???
|
||||||
|
P=???
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
VARIABLES T P
|
||||||
|
|
||||||
|
T <: My<T>
|
||||||
|
Inv<P> <: Inv<T>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
interface Inv<I>
|
||||||
|
interface Inv2<I>
|
||||||
|
|
||||||
|
fun <T: Inv2<T>> foo(klass: Inv<T>): String? = null
|
||||||
|
|
||||||
|
fun <X> bar(): Inv<X> = null!!
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>bar<!>())
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun </*0*/ X> bar(): Inv<X>
|
||||||
|
internal fun </*0*/ T : Inv2<T>> foo(/*0*/ klass: Inv<T>): kotlin.String?
|
||||||
|
internal fun test(): kotlin.Unit
|
||||||
|
|
||||||
|
internal interface Inv</*0*/ I> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface Inv2</*0*/ I> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -7226,6 +7226,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt8879.kt")
|
||||||
|
public void testKt8879() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/constraints/kt8879.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("notNullConstraintOnNullableType.kt")
|
@TestMetadata("notNullConstraintOnNullableType.kt")
|
||||||
public void testNotNullConstraintOnNullableType() throws Exception {
|
public void testNotNullConstraintOnNullableType() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/constraints/notNullConstraintOnNullableType.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/constraints/notNullConstraintOnNullableType.kt");
|
||||||
|
|||||||
+5
-4
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
|||||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.resolve.TypeResolver
|
import org.jetbrains.kotlin.resolve.TypeResolver
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.SPECIAL
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.SPECIAL
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.registerTypeVariables
|
import org.jetbrains.kotlin.resolve.calls.inference.registerTypeVariables
|
||||||
@@ -92,12 +93,12 @@ abstract public class AbstractConstraintSystemTest() : JetLiteFixture() {
|
|||||||
for (constraint in constraints) {
|
for (constraint in constraints) {
|
||||||
val firstType = testDeclarations.getType(constraint.firstType).assertNotError()
|
val firstType = testDeclarations.getType(constraint.firstType).assertNotError()
|
||||||
val secondType = testDeclarations.getType(constraint.secondType).assertNotError()
|
val secondType = testDeclarations.getType(constraint.secondType).assertNotError()
|
||||||
val position = SPECIAL.position()
|
val context = ConstraintContext(SPECIAL.position())
|
||||||
when (constraint.kind) {
|
when (constraint.kind) {
|
||||||
MyConstraintKind.SUBTYPE -> constraintSystem.addSubtypeConstraint(firstType, secondType, position)
|
MyConstraintKind.SUBTYPE -> constraintSystem.addSubtypeConstraint(firstType, secondType, context.position)
|
||||||
MyConstraintKind.SUPERTYPE -> constraintSystem.addSupertypeConstraint(firstType, secondType, position)
|
MyConstraintKind.SUPERTYPE -> constraintSystem.addSupertypeConstraint(firstType, secondType, context.position)
|
||||||
MyConstraintKind.EQUAL -> constraintSystem.addConstraint(
|
MyConstraintKind.EQUAL -> constraintSystem.addConstraint(
|
||||||
ConstraintSystemImpl.ConstraintKind.EQUAL, firstType, secondType, position, topLevel = true)
|
ConstraintSystemImpl.ConstraintKind.EQUAL, firstType, secondType, context, topLevel = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fixVariables) constraintSystem.fixVariables()
|
if (fixVariables) constraintSystem.fixVariables()
|
||||||
|
|||||||
+6
@@ -720,6 +720,12 @@ public class ConstraintSystemTestGenerated extends AbstractConstraintSystemTest
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt8879.constraints")
|
||||||
|
public void testKt8879() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/constraintSystem/severalVariables/recursive/kt8879.constraints");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("mutuallyRecursive.constraints")
|
@TestMetadata("mutuallyRecursive.constraints")
|
||||||
public void testMutuallyRecursive() throws Exception {
|
public void testMutuallyRecursive() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/constraintSystem/severalVariables/recursive/mutuallyRecursive.constraints");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/constraintSystem/severalVariables/recursive/mutuallyRecursive.constraints");
|
||||||
|
|||||||
+28
-23
@@ -153,8 +153,8 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
for ((typeVariable, typeBounds) in allTypeParameterBounds) {
|
for ((typeVariable, typeBounds) in allTypeParameterBounds) {
|
||||||
for (declaredUpperBound in typeVariable.getUpperBounds()) {
|
for (declaredUpperBound in typeVariable.getUpperBounds()) {
|
||||||
if (declaredUpperBound.isDefaultBound()) continue //todo remove this line (?)
|
if (declaredUpperBound.isDefaultBound()) continue //todo remove this line (?)
|
||||||
val position = TYPE_BOUND_POSITION.position(typeVariable.getIndex())
|
val context = ConstraintContext(TYPE_BOUND_POSITION.position(typeVariable.getIndex()))
|
||||||
addBound(typeVariable, declaredUpperBound, UPPER_BOUND, position)
|
addBound(typeVariable, declaredUpperBound, UPPER_BOUND, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,27 +204,31 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
|
if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return
|
||||||
|
|
||||||
val newSubjectType = originalToVariablesSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
val newSubjectType = originalToVariablesSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
||||||
addConstraint(SUB_TYPE, newSubjectType, constrainingType, constraintPosition, topLevel = true)
|
addConstraint(SUB_TYPE, newSubjectType, constrainingType, ConstraintContext(constraintPosition), topLevel = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addSubtypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) {
|
override fun addSubtypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) {
|
||||||
val newSubjectType = originalToVariablesSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
val newSubjectType = originalToVariablesSubstitutor.substitute(subjectType, Variance.INVARIANT)
|
||||||
addConstraint(SUB_TYPE, constrainingType, newSubjectType, constraintPosition, topLevel = true)
|
addConstraint(SUB_TYPE, constrainingType, newSubjectType, ConstraintContext(constraintPosition), topLevel = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addConstraint(
|
fun addConstraint(
|
||||||
constraintKind: ConstraintKind,
|
constraintKind: ConstraintKind,
|
||||||
subType: JetType?,
|
subType: JetType?,
|
||||||
superType: JetType?,
|
superType: JetType?,
|
||||||
constraintPosition: ConstraintPosition,
|
constraintContext: ConstraintContext,
|
||||||
topLevel: Boolean
|
topLevel: Boolean
|
||||||
) {
|
) {
|
||||||
|
val constraintPosition = constraintContext.position
|
||||||
|
|
||||||
|
// when processing nested constraints, `derivedFrom` information should be reset
|
||||||
|
val newConstraintContext = ConstraintContext(constraintContext.position, derivedFrom = null)
|
||||||
val typeCheckingProcedure = TypeCheckingProcedure(object : TypeCheckingProcedureCallbacks {
|
val typeCheckingProcedure = TypeCheckingProcedure(object : TypeCheckingProcedureCallbacks {
|
||||||
private var depth = 0
|
private var depth = 0
|
||||||
|
|
||||||
override fun assertEqualTypes(a: JetType, b: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean {
|
override fun assertEqualTypes(a: JetType, b: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean {
|
||||||
depth++
|
depth++
|
||||||
doAddConstraint(EQUAL, a, b, constraintPosition, typeCheckingProcedure, topLevel = false)
|
doAddConstraint(EQUAL, a, b, newConstraintContext, typeCheckingProcedure, topLevel = false)
|
||||||
depth--
|
depth--
|
||||||
return true
|
return true
|
||||||
|
|
||||||
@@ -236,7 +240,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
|
|
||||||
override fun assertSubtype(subtype: JetType, supertype: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean {
|
override fun assertSubtype(subtype: JetType, supertype: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean {
|
||||||
depth++
|
depth++
|
||||||
doAddConstraint(SUB_TYPE, subtype, supertype, constraintPosition, typeCheckingProcedure, topLevel = false)
|
doAddConstraint(SUB_TYPE, subtype, supertype, newConstraintContext, typeCheckingProcedure, topLevel = false)
|
||||||
depth--
|
depth--
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -249,7 +253,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
errors.add(CannotCapture(constraintPosition, myTypeVariable))
|
errors.add(CannotCapture(constraintPosition, myTypeVariable))
|
||||||
}
|
}
|
||||||
generateTypeParameterCaptureConstraint(typeVariable, typeProjection, constraintPosition)
|
generateTypeParameterCaptureConstraint(typeVariable, typeProjection, newConstraintContext)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -260,7 +264,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
doAddConstraint(constraintKind, subType, superType, constraintPosition, typeCheckingProcedure, topLevel)
|
doAddConstraint(constraintKind, subType, superType, constraintContext, typeCheckingProcedure, topLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isErrorOrSpecialType(type: JetType?, constraintPosition: ConstraintPosition): Boolean {
|
private fun isErrorOrSpecialType(type: JetType?, constraintPosition: ConstraintPosition): Boolean {
|
||||||
@@ -279,10 +283,11 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
constraintKind: ConstraintKind,
|
constraintKind: ConstraintKind,
|
||||||
subType: JetType?,
|
subType: JetType?,
|
||||||
superType: JetType?,
|
superType: JetType?,
|
||||||
constraintPosition: ConstraintPosition,
|
constraintContext: ConstraintContext,
|
||||||
typeCheckingProcedure: TypeCheckingProcedure,
|
typeCheckingProcedure: TypeCheckingProcedure,
|
||||||
topLevel: Boolean
|
topLevel: Boolean
|
||||||
) {
|
) {
|
||||||
|
val constraintPosition = constraintContext.position
|
||||||
if (isErrorOrSpecialType(subType, constraintPosition) || isErrorOrSpecialType(superType, constraintPosition)) return
|
if (isErrorOrSpecialType(subType, constraintPosition) || isErrorOrSpecialType(superType, constraintPosition)) return
|
||||||
if (subType == null || superType == null) return
|
if (subType == null || superType == null) return
|
||||||
|
|
||||||
@@ -306,11 +311,11 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
|
|
||||||
fun simplifyConstraint(subType: JetType, superType: JetType) {
|
fun simplifyConstraint(subType: JetType, superType: JetType) {
|
||||||
if (isMyTypeVariable(subType)) {
|
if (isMyTypeVariable(subType)) {
|
||||||
generateTypeParameterBound(subType, superType, constraintKind.toBound(), constraintPosition)
|
generateTypeParameterBound(subType, superType, constraintKind.toBound(), constraintContext)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (isMyTypeVariable(superType)) {
|
if (isMyTypeVariable(superType)) {
|
||||||
generateTypeParameterBound(superType, subType, constraintKind.toBound().reverse(), constraintPosition)
|
generateTypeParameterBound(superType, subType, constraintKind.toBound().reverse(), constraintContext)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// if subType is nullable and superType is not nullable, unsafe call or type mismatch error will be generated later,
|
// if subType is nullable and superType is not nullable, unsafe call or type mismatch error will be generated later,
|
||||||
@@ -335,10 +340,10 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
typeVariable: TypeParameterDescriptor,
|
typeVariable: TypeParameterDescriptor,
|
||||||
constrainingType: JetType,
|
constrainingType: JetType,
|
||||||
kind: TypeBounds.BoundKind,
|
kind: TypeBounds.BoundKind,
|
||||||
position: ConstraintPosition,
|
constraintContext: ConstraintContext
|
||||||
derivedFrom: Set<TypeParameterDescriptor> = emptySet()
|
|
||||||
) {
|
) {
|
||||||
val bound = Bound(typeVariable, constrainingType, kind, position, constrainingType.isProper(), derivedFrom)
|
val bound = Bound(typeVariable, constrainingType, kind, constraintContext.position,
|
||||||
|
constrainingType.isProper(), constraintContext.derivedFrom ?: emptySet())
|
||||||
val typeBounds = getTypeBounds(typeVariable)
|
val typeBounds = getTypeBounds(typeVariable)
|
||||||
if (typeBounds.bounds.contains(bound)) return
|
if (typeBounds.bounds.contains(bound)) return
|
||||||
|
|
||||||
@@ -358,7 +363,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
parameterType: JetType,
|
parameterType: JetType,
|
||||||
constrainingType: JetType,
|
constrainingType: JetType,
|
||||||
boundKind: TypeBounds.BoundKind,
|
boundKind: TypeBounds.BoundKind,
|
||||||
constraintPosition: ConstraintPosition
|
constraintContext: ConstraintContext
|
||||||
) {
|
) {
|
||||||
val typeVariable = getMyTypeVariable(parameterType)!!
|
val typeVariable = getMyTypeVariable(parameterType)!!
|
||||||
|
|
||||||
@@ -380,7 +385,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!parameterType.isMarkedNullable() || !TypeUtils.isNullableType(newConstrainingType)) {
|
if (!parameterType.isMarkedNullable() || !TypeUtils.isNullableType(newConstrainingType)) {
|
||||||
addBound(typeVariable, newConstrainingType, boundKind, constraintPosition)
|
addBound(typeVariable, newConstrainingType, boundKind, constraintContext)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// For parameter type T:
|
// For parameter type T:
|
||||||
@@ -390,23 +395,23 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
// constraints T? >: Int?; T? >: Int! should transform to T >: Int
|
// constraints T? >: Int?; T? >: Int! should transform to T >: Int
|
||||||
val notNullConstrainingType = TypeUtils.makeNotNullable(newConstrainingType)
|
val notNullConstrainingType = TypeUtils.makeNotNullable(newConstrainingType)
|
||||||
if (boundKind == EXACT_BOUND || boundKind == LOWER_BOUND) {
|
if (boundKind == EXACT_BOUND || boundKind == LOWER_BOUND) {
|
||||||
addBound(typeVariable, notNullConstrainingType, LOWER_BOUND, constraintPosition)
|
addBound(typeVariable, notNullConstrainingType, LOWER_BOUND, constraintContext)
|
||||||
}
|
}
|
||||||
// constraints T? <: Int?; T? <: Int! should transform to T <: Int?; T <: Int! correspondingly
|
// constraints T? <: Int?; T? <: Int! should transform to T <: Int?; T <: Int! correspondingly
|
||||||
if (boundKind == EXACT_BOUND || boundKind == UPPER_BOUND) {
|
if (boundKind == EXACT_BOUND || boundKind == UPPER_BOUND) {
|
||||||
addBound(typeVariable, newConstrainingType, UPPER_BOUND, constraintPosition)
|
addBound(typeVariable, newConstrainingType, UPPER_BOUND, constraintContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateTypeParameterCaptureConstraint(
|
private fun generateTypeParameterCaptureConstraint(
|
||||||
parameterType: JetType,
|
parameterType: JetType,
|
||||||
constrainingTypeProjection: TypeProjection,
|
constrainingTypeProjection: TypeProjection,
|
||||||
constraintPosition: ConstraintPosition
|
constraintContext: ConstraintContext
|
||||||
) {
|
) {
|
||||||
val typeVariable = getMyTypeVariable(parameterType)!!
|
val typeVariable = getMyTypeVariable(parameterType)!!
|
||||||
if (!typeVariable.getUpperBoundsAsType().isDefaultBound()
|
if (!typeVariable.getUpperBoundsAsType().isDefaultBound()
|
||||||
&& constrainingTypeProjection.getProjectionKind() == Variance.IN_VARIANCE) {
|
&& constrainingTypeProjection.getProjectionKind() == Variance.IN_VARIANCE) {
|
||||||
errors.add(CannotCapture(constraintPosition, typeVariable))
|
errors.add(CannotCapture(constraintContext.position, typeVariable))
|
||||||
}
|
}
|
||||||
val typeProjection = if (parameterType.isMarkedNullable()) {
|
val typeProjection = if (parameterType.isMarkedNullable()) {
|
||||||
TypeProjectionImpl(constrainingTypeProjection.getProjectionKind(), TypeUtils.makeNotNullable(constrainingTypeProjection.getType()))
|
TypeProjectionImpl(constrainingTypeProjection.getProjectionKind(), TypeUtils.makeNotNullable(constrainingTypeProjection.getType()))
|
||||||
@@ -415,7 +420,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
constrainingTypeProjection
|
constrainingTypeProjection
|
||||||
}
|
}
|
||||||
val capturedType = createCapturedType(typeProjection)
|
val capturedType = createCapturedType(typeProjection)
|
||||||
addBound(typeVariable, capturedType, EXACT_BOUND, constraintPosition)
|
addBound(typeVariable, capturedType, EXACT_BOUND, constraintContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTypeVariables() = originalToVariables.keySet()
|
override fun getTypeVariables() = originalToVariables.keySet()
|
||||||
@@ -483,7 +488,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
|
|
||||||
val value = typeBounds.value ?: return
|
val value = typeBounds.value ?: return
|
||||||
|
|
||||||
addBound(typeVariable, value, TypeBounds.BoundKind.EXACT_BOUND, ConstraintPositionKind.FROM_COMPLETER.position())
|
addBound(typeVariable, value, TypeBounds.BoundKind.EXACT_BOUND, ConstraintContext(ConstraintPositionKind.FROM_COMPLETER.position()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fixVariables() {
|
fun fixVariables() {
|
||||||
|
|||||||
+14
-6
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
||||||
@@ -24,12 +25,18 @@ import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.EXACT_B
|
|||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.CompoundConstraintPosition
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.CompoundConstraintPosition
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
||||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
||||||
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
data class ConstraintContext(
|
||||||
|
val position: ConstraintPosition,
|
||||||
|
// see TypeBounds.Bound.derivedFrom
|
||||||
|
val derivedFrom: Set<TypeParameterDescriptor>? = null)
|
||||||
|
|
||||||
fun ConstraintSystemImpl.incorporateBound(newBound: Bound) {
|
fun ConstraintSystemImpl.incorporateBound(newBound: Bound) {
|
||||||
val typeVariable = newBound.typeVariable
|
val typeVariable = newBound.typeVariable
|
||||||
val typeBounds = getTypeBounds(typeVariable)
|
val typeBounds = getTypeBounds(typeVariable)
|
||||||
@@ -45,7 +52,8 @@ fun ConstraintSystemImpl.incorporateBound(newBound: Bound) {
|
|||||||
|
|
||||||
val constrainingType = newBound.constrainingType
|
val constrainingType = newBound.constrainingType
|
||||||
if (isMyTypeVariable(constrainingType)) {
|
if (isMyTypeVariable(constrainingType)) {
|
||||||
addBound(getMyTypeVariable(constrainingType)!!, typeVariable.correspondingType, newBound.kind.reverse(), newBound.position)
|
val context = ConstraintContext(newBound.position, newBound.derivedFrom)
|
||||||
|
addBound(getMyTypeVariable(constrainingType)!!, typeVariable.correspondingType, newBound.kind.reverse(), context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
constrainingType.getNestedTypeVariables().forEach {
|
constrainingType.getNestedTypeVariables().forEach {
|
||||||
@@ -61,12 +69,12 @@ private fun ConstraintSystemImpl.addConstraintFromBounds(old: Bound, new: Bound)
|
|||||||
|
|
||||||
val oldType = old.constrainingType
|
val oldType = old.constrainingType
|
||||||
val newType = new.constrainingType
|
val newType = new.constrainingType
|
||||||
val position = CompoundConstraintPosition(old.position, new.position)
|
val context = ConstraintContext(CompoundConstraintPosition(old.position, new.position), old.derivedFrom + new.derivedFrom)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
old.kind.ordinal() < new.kind.ordinal() -> addConstraint(SUB_TYPE, oldType, newType, position, topLevel = false)
|
old.kind.ordinal() < new.kind.ordinal() -> addConstraint(SUB_TYPE, oldType, newType, context, topLevel = false)
|
||||||
old.kind.ordinal() > new.kind.ordinal() -> addConstraint(SUB_TYPE, newType, oldType, position, topLevel = false)
|
old.kind.ordinal() > new.kind.ordinal() -> addConstraint(SUB_TYPE, newType, oldType, context, topLevel = false)
|
||||||
old.kind == new.kind && old.kind == EXACT_BOUND -> addConstraint(EQUAL, oldType, newType, position, topLevel = false)
|
old.kind == new.kind && old.kind == EXACT_BOUND -> addConstraint(EQUAL, oldType, newType, context, topLevel = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +105,7 @@ private fun ConstraintSystemImpl.generateNewBound(bound: Bound, substitution: Bo
|
|||||||
if (derivedFrom.contains(substitution.typeVariable)) return
|
if (derivedFrom.contains(substitution.typeVariable)) return
|
||||||
|
|
||||||
derivedFrom.add(substitution.typeVariable)
|
derivedFrom.add(substitution.typeVariable)
|
||||||
addBound(bound.typeVariable, newConstrainingType, newBoundKind, position, derivedFrom)
|
addBound(bound.typeVariable, newConstrainingType, newBoundKind, ConstraintContext(position, derivedFrom))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (substitution.kind == EXACT_BOUND) {
|
if (substitution.kind == EXACT_BOUND) {
|
||||||
|
|||||||
Reference in New Issue
Block a user