From 0bed055fcae63c57b5c88f24062c7ea50c3db6d1 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Wed, 27 May 2020 12:19:02 +0300 Subject: [PATCH] NI: small refactoring around `TypeCheckerContext` and adding new possible constraints --- .../components/ConstraintIncorporator.kt | 14 ++- .../components/ConstraintInjector.kt | 102 ++++++++++-------- 2 files changed, 65 insertions(+), 51 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt index fe83dd060f2..15776a2b2b4 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt @@ -38,22 +38,26 @@ class ConstraintIncorporator( fun addNewIncorporatedConstraint(typeVariable: TypeVariableMarker, type: KotlinTypeMarker, constraintContext: ConstraintContext) } - fun incorporateIntoOtherConstraints(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) = + fun incorporateIntoOtherConstraints(c: Context, typeVariable: TypeVariableMarker, constraint: Constraint) { + // we shouldn't incorporate recursive constraint -- It is too dangerous + if (c.areThereRecursiveConstraints(typeVariable, constraint)) return + 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 - with(c) { - val freshTypeConstructor = typeVariable.freshTypeConstructor() - if (constraint.type.contains { it.typeConstructor() == freshTypeConstructor }) return - } + if (c.areThereRecursiveConstraints(typeVariable, constraint)) return c.directWithVariable(typeVariable, constraint) c.otherInsideMyConstraint(typeVariable, constraint) c.insideOtherConstraint(typeVariable, constraint) } + private fun Context.areThereRecursiveConstraints(typeVariable: TypeVariableMarker, constraint: Constraint) = + constraint.type.contains { it.typeConstructor() == typeVariable.freshTypeConstructor() } + // A <:(=) \alpha <:(=) B => A <: B private fun Context.directWithVariable( typeVariable: TypeVariableMarker, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt index 5740135d8dc..8763133495e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.refinement.TypeRefinement -import org.jetbrains.kotlin.utils.SmartList import kotlin.math.max class ConstraintInjector( @@ -47,47 +46,51 @@ class ConstraintInjector( } fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) { - val initialConstraint = InitialConstraint(lowerType, upperType, UPPER, position) - c.addInitialConstraint(initialConstraint) + val initialConstraint = InitialConstraint(lowerType, upperType, UPPER, position).also { c.addInitialConstraint(it) } + updateAllowedTypeDepth(c, lowerType) updateAllowedTypeDepth(c, upperType) - addSubTypeConstraintAndIncorporateIt(c, lowerType, upperType, IncorporationConstraintPosition(position, initialConstraint)) + + addSubTypeConstraintAndIncorporateIt( + c, + lowerType, + upperType, + TypeCheckerContext(c, IncorporationConstraintPosition(position, initialConstraint)) + ) } fun addInitialEqualityConstraint(c: Context, a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) { - val initialConstraint = InitialConstraint(a, b, EQUALITY, position) - c.addInitialConstraint(initialConstraint) + val initialConstraint = InitialConstraint(a, b, EQUALITY, position).also { c.addInitialConstraint(it) } + updateAllowedTypeDepth(c, a) updateAllowedTypeDepth(c, b) - addSubTypeConstraintAndIncorporateIt(c, a, b, IncorporationConstraintPosition(position, initialConstraint)) - addSubTypeConstraintAndIncorporateIt(c, b, a, IncorporationConstraintPosition(position, initialConstraint)) + + val incorporationConstraintPosition = IncorporationConstraintPosition(position, initialConstraint) + val typeCheckerContext = TypeCheckerContext(c, incorporationConstraintPosition) + + if (position is FixVariableConstraintPosition) { + c.incorporateEqualityConstraintForFixingTypeVariable( + incorporationConstraintPosition, position.variable, resultType = b, typeCheckerContext + ) + } + + addSubTypeConstraintAndIncorporateIt(c, a, b, typeCheckerContext) + addSubTypeConstraintAndIncorporateIt(c, b, a, typeCheckerContext) } private fun addSubTypeConstraintAndIncorporateIt( c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, - incorporatePosition: IncorporationConstraintPosition + typeCheckerContext: TypeCheckerContext ) { - var possibleNewConstraints: MutableList>? = null - - val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType) { typeVar, constraint -> - if (possibleNewConstraints == null) { - possibleNewConstraints = SmartList() - } - possibleNewConstraints!!.add(typeVar to constraint) - } + typeCheckerContext.setConstrainingTypesToPrintDebugInfo(lowerType, upperType) typeCheckerContext.runIsSubtypeOf(lowerType, upperType) + var constraintsFromIsSubtype = true - 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!!) { + while (typeCheckerContext.hasConstraintsToProcess()) { + for ((typeVariable, constraint) in typeCheckerContext.extractAllConstraints()) { if (c.shouldWeSkipConstraint(typeVariable, constraint, constraintsFromIsSubtype)) continue val constraints = @@ -102,7 +105,7 @@ class ConstraintInjector( } val contextOps = c as? ConstraintSystemOperation - if (possibleNewConstraints == null || + if (!typeCheckerContext.hasConstraintsToProcess() || (contextOps != null && c.notFixedTypeVariables.all { typeVariable -> typeVariable.value.constraints.any { constraint -> constraint.kind == EQUALITY && contextOps.isProperType(constraint.type) @@ -121,24 +124,18 @@ class ConstraintInjector( private fun Context.incorporateEqualityConstraintForFixingTypeVariable( incorporatePosition: IncorporationConstraintPosition, + fixingTypeVariable: TypeVariableMarker, + resultType: KotlinTypeMarker, typeCheckerContext: TypeCheckerContext ) { - if (incorporatePosition.from !is FixVariableConstraintPosition) return + if (resultType.isUninferredParameter() || resultType.isError()) return - val typeToIncorporate = incorporatePosition.initialConstraint.b - - if (typeToIncorporate.isUninferredParameter() || typeToIncorporate.isError()) return + assert(!resultType.contains { it.typeConstructor() is TypeVariableTypeConstructor }) constraintIncorporator.incorporateIntoOtherConstraints( typeCheckerContext, - incorporatePosition.from.variable, - Constraint( - EQUALITY, - typeToIncorporate, - incorporatePosition, - derivedFrom = setOf(), - isNullabilityConstraint = false - ) + fixingTypeVariable, + Constraint(EQUALITY, resultType, incorporatePosition, derivedFrom = emptySet(), isNullabilityConstraint = false) ) } @@ -172,13 +169,25 @@ class ConstraintInjector( private fun Context.isAllowedType(type: KotlinTypeMarker) = type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION - private inner class TypeCheckerContext( - val c: Context, - val position: IncorporationConstraintPosition, - val baseLowerType: KotlinTypeMarker, - val baseUpperType: KotlinTypeMarker, - val addPossibleNewConstraints: (TypeVariableMarker, Constraint) -> Unit - ) : AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c { + private inner class TypeCheckerContext(val c: Context, val position: IncorporationConstraintPosition) : + AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c { + private val newPossibleConstraints = mutableSetOf>() + + private var baseLowerType = position.initialConstraint.a + private var baseUpperType = position.initialConstraint.b + + fun extractAllConstraints(): Set> { + val newConstraintsSet = newPossibleConstraints.toSet() + newPossibleConstraints.clear() + return newConstraintsSet + } + + fun hasConstraintsToProcess() = newPossibleConstraints.isNotEmpty() + + fun setConstrainingTypesToPrintDebugInfo(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) { + baseLowerType = lowerType + baseUpperType = upperType + } val baseContext: AbstractTypeCheckerContext = newBaseTypeCheckerContext(isErrorTypeEqualsToAnything, isStubTypeEqualsToAnything) @@ -333,7 +342,8 @@ class ConstraintInjector( isNullabilityConstraint = isNullabilityConstraint, inputTypePositionBeforeIncorporation = inputTypePosition ) - addPossibleNewConstraints(typeVariable, newConstraint) + + newPossibleConstraints.add(typeVariable to newConstraint) } override val allTypeVariablesWithConstraints: Collection