Don't generate constraint if a type variable was substituted twice
to prevent infinite recursion
This commit is contained in:
+26
@@ -0,0 +1,26 @@
|
||||
VARIABLES T P E
|
||||
|
||||
SUBTYPE T Producer<P>
|
||||
SUBTYPE P Producer<E>
|
||||
SUBTYPE E Producer<P>
|
||||
|
||||
type parameter bounds:
|
||||
T <: Producer<P>*, <: Producer<Producer<E>>*, <: Producer<Producer<Producer<P>>>*
|
||||
P <: Producer<E>*
|
||||
E <: Producer<P>*
|
||||
|
||||
status:
|
||||
-hasCannotCaptureTypesError: false
|
||||
-hasConflictingConstraints: false
|
||||
-hasContradiction: false
|
||||
-hasErrorInConstrainingTypes: false
|
||||
-hasTypeConstructorMismatch: false
|
||||
-hasTypeInferenceIncorporationError: false
|
||||
-hasUnknownParameters: true
|
||||
-hasViolatedUpperBound: false
|
||||
-isSuccessful: false
|
||||
|
||||
result:
|
||||
T=???
|
||||
P=???
|
||||
E=???
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
VARIABLES T P E
|
||||
|
||||
SUBTYPE T Producer<P>
|
||||
SUBTYPE P Producer<E>
|
||||
SUBTYPE E Producer<P>
|
||||
+6
@@ -441,6 +441,12 @@ public class ConstraintSystemTestGenerated extends AbstractConstraintSystemTest
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/constraintSystem/severalVariables/recursive"), Pattern.compile("^(.+)\\.constraints$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("implicitlyRecursive.constraints")
|
||||
public void testImplicitlyRecursive() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/constraintSystem/severalVariables/recursive/implicitlyRecursive.constraints");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("mutuallyRecursive.constraints")
|
||||
public void testMutuallyRecursive() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/constraintSystem/severalVariables/recursive/mutuallyRecursive.constraints");
|
||||
|
||||
+3
-2
@@ -346,9 +346,10 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
||||
typeVariable: TypeParameterDescriptor,
|
||||
constrainingType: JetType,
|
||||
kind: TypeBounds.BoundKind,
|
||||
position: ConstraintPosition
|
||||
position: ConstraintPosition,
|
||||
derivedFrom: Set<TypeParameterDescriptor> = emptySet()
|
||||
) {
|
||||
val bound = Bound(typeVariable, constrainingType, kind, position, constrainingType.isProper())
|
||||
val bound = Bound(typeVariable, constrainingType, kind, position, constrainingType.isProper(), derivedFrom)
|
||||
val typeBounds = getTypeBounds(typeVariable)
|
||||
if (typeBounds.bounds.contains(bound)) return
|
||||
|
||||
|
||||
@@ -49,7 +49,9 @@ public trait TypeBounds {
|
||||
public val constrainingType: JetType,
|
||||
public val kind: BoundKind,
|
||||
public val position: ConstraintPosition,
|
||||
public val isProper: Boolean = true
|
||||
public val isProper: Boolean,
|
||||
// to prevent infinite recursion in incorporation we store the variables that was substituted to derive this bound
|
||||
public val derivedFrom: Set<TypeParameterDescriptor>
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
@@ -194,7 +194,8 @@ fun Collection<Bound>.substitute(substituteTypeVariable: (TypeParameterDescripto
|
||||
it.constrainingType
|
||||
}
|
||||
substitutedType?.let { type ->
|
||||
Bound(substituteTypeVariable(it.typeVariable) ?: it.typeVariable, type, it.kind, it.position, it.isProper)
|
||||
Bound(substituteTypeVariable(it.typeVariable) ?: it.typeVariable, type, it.kind, it.position, it.isProper,
|
||||
it.derivedFrom.map { substituteTypeVariable(it) ?: it }.toSet())
|
||||
}
|
||||
}.filterNotNull()
|
||||
}
|
||||
|
||||
+8
-2
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
||||
import org.jetbrains.kotlin.types.typeUtil.getNestedTypeArguments
|
||||
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||
import java.util.*
|
||||
|
||||
fun ConstraintSystemImpl.incorporateBound(newBound: Bound) {
|
||||
val typeVariable = newBound.typeVariable
|
||||
@@ -92,9 +93,14 @@ private fun ConstraintSystemImpl.generateNewBound(bound: Bound, substitution: Bo
|
||||
fun addNewBound(newConstrainingType: JetType, newBoundKind: BoundKind) {
|
||||
// We don't generate new recursive constraints
|
||||
val nestedTypeVariables = newConstrainingType.getNestedTypeVariables()
|
||||
if (nestedTypeVariables.contains(bound.typeVariable) || nestedTypeVariables.contains(substitution.typeVariable)) return
|
||||
if (nestedTypeVariables.contains(bound.typeVariable)) return
|
||||
|
||||
addBound(bound.typeVariable, newConstrainingType, newBoundKind, position)
|
||||
// We don't generate constraint if a type variable was substituted twice
|
||||
val derivedFrom = HashSet(bound.derivedFrom + substitution.derivedFrom)
|
||||
if (derivedFrom.contains(substitution.typeVariable)) return
|
||||
|
||||
derivedFrom.add(substitution.typeVariable)
|
||||
addBound(bound.typeVariable, newConstrainingType, newBoundKind, position, derivedFrom)
|
||||
}
|
||||
|
||||
if (substitution.kind == EXACT_BOUND) {
|
||||
|
||||
Reference in New Issue
Block a user