NI: small refactoring around TypeCheckerContext and adding new possible constraints
This commit is contained in:
+9
-5
@@ -38,22 +38,26 @@ 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) =
|
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)
|
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
|
||||||
with(c) {
|
if (c.areThereRecursiveConstraints(typeVariable, constraint)) return
|
||||||
val freshTypeConstructor = typeVariable.freshTypeConstructor()
|
|
||||||
if (constraint.type.contains { it.typeConstructor() == freshTypeConstructor }) return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.directWithVariable(typeVariable, constraint)
|
c.directWithVariable(typeVariable, constraint)
|
||||||
c.otherInsideMyConstraint(typeVariable, constraint)
|
c.otherInsideMyConstraint(typeVariable, constraint)
|
||||||
c.insideOtherConstraint(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
|
// A <:(=) \alpha <:(=) B => A <: B
|
||||||
private fun Context.directWithVariable(
|
private fun Context.directWithVariable(
|
||||||
typeVariable: TypeVariableMarker,
|
typeVariable: TypeVariableMarker,
|
||||||
|
|||||||
+56
-46
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.types.*
|
|||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
class ConstraintInjector(
|
class ConstraintInjector(
|
||||||
@@ -47,47 +46,51 @@ class ConstraintInjector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) {
|
fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) {
|
||||||
val initialConstraint = InitialConstraint(lowerType, upperType, UPPER, position)
|
val initialConstraint = InitialConstraint(lowerType, upperType, UPPER, position).also { c.addInitialConstraint(it) }
|
||||||
c.addInitialConstraint(initialConstraint)
|
|
||||||
updateAllowedTypeDepth(c, lowerType)
|
updateAllowedTypeDepth(c, lowerType)
|
||||||
updateAllowedTypeDepth(c, upperType)
|
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) {
|
fun addInitialEqualityConstraint(c: Context, a: KotlinTypeMarker, b: KotlinTypeMarker, position: ConstraintPosition) {
|
||||||
val initialConstraint = InitialConstraint(a, b, EQUALITY, position)
|
val initialConstraint = InitialConstraint(a, b, EQUALITY, position).also { c.addInitialConstraint(it) }
|
||||||
c.addInitialConstraint(initialConstraint)
|
|
||||||
updateAllowedTypeDepth(c, a)
|
updateAllowedTypeDepth(c, a)
|
||||||
updateAllowedTypeDepth(c, b)
|
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(
|
private fun addSubTypeConstraintAndIncorporateIt(
|
||||||
c: Context,
|
c: Context,
|
||||||
lowerType: KotlinTypeMarker,
|
lowerType: KotlinTypeMarker,
|
||||||
upperType: KotlinTypeMarker,
|
upperType: KotlinTypeMarker,
|
||||||
incorporatePosition: IncorporationConstraintPosition
|
typeCheckerContext: TypeCheckerContext
|
||||||
) {
|
) {
|
||||||
var possibleNewConstraints: MutableList<Pair<TypeVariableMarker, Constraint>>? = null
|
typeCheckerContext.setConstrainingTypesToPrintDebugInfo(lowerType, upperType)
|
||||||
|
|
||||||
val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType) { typeVar, constraint ->
|
|
||||||
if (possibleNewConstraints == null) {
|
|
||||||
possibleNewConstraints = SmartList()
|
|
||||||
}
|
|
||||||
possibleNewConstraints!!.add(typeVar to constraint)
|
|
||||||
}
|
|
||||||
typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
|
typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
|
||||||
|
|
||||||
var constraintsFromIsSubtype = true
|
var constraintsFromIsSubtype = true
|
||||||
|
|
||||||
if (incorporatePosition.from is FixVariableConstraintPosition && lowerType == incorporatePosition.initialConstraint.a) {
|
while (typeCheckerContext.hasConstraintsToProcess()) {
|
||||||
c.incorporateEqualityConstraintForFixingTypeVariable(incorporatePosition, typeCheckerContext)
|
for ((typeVariable, constraint) in typeCheckerContext.extractAllConstraints()) {
|
||||||
}
|
|
||||||
|
|
||||||
while (possibleNewConstraints != null) {
|
|
||||||
val constraintsToProcess = possibleNewConstraints
|
|
||||||
possibleNewConstraints = null
|
|
||||||
for ((typeVariable, constraint) in constraintsToProcess!!) {
|
|
||||||
if (c.shouldWeSkipConstraint(typeVariable, constraint, constraintsFromIsSubtype)) continue
|
if (c.shouldWeSkipConstraint(typeVariable, constraint, constraintsFromIsSubtype)) continue
|
||||||
|
|
||||||
val constraints =
|
val constraints =
|
||||||
@@ -102,7 +105,7 @@ class ConstraintInjector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val contextOps = c as? ConstraintSystemOperation
|
val contextOps = c as? ConstraintSystemOperation
|
||||||
if (possibleNewConstraints == null ||
|
if (!typeCheckerContext.hasConstraintsToProcess() ||
|
||||||
(contextOps != null && c.notFixedTypeVariables.all { typeVariable ->
|
(contextOps != null && c.notFixedTypeVariables.all { typeVariable ->
|
||||||
typeVariable.value.constraints.any { constraint ->
|
typeVariable.value.constraints.any { constraint ->
|
||||||
constraint.kind == EQUALITY && contextOps.isProperType(constraint.type)
|
constraint.kind == EQUALITY && contextOps.isProperType(constraint.type)
|
||||||
@@ -121,24 +124,18 @@ class ConstraintInjector(
|
|||||||
|
|
||||||
private fun Context.incorporateEqualityConstraintForFixingTypeVariable(
|
private fun Context.incorporateEqualityConstraintForFixingTypeVariable(
|
||||||
incorporatePosition: IncorporationConstraintPosition,
|
incorporatePosition: IncorporationConstraintPosition,
|
||||||
|
fixingTypeVariable: TypeVariableMarker,
|
||||||
|
resultType: KotlinTypeMarker,
|
||||||
typeCheckerContext: TypeCheckerContext
|
typeCheckerContext: TypeCheckerContext
|
||||||
) {
|
) {
|
||||||
if (incorporatePosition.from !is FixVariableConstraintPosition) return
|
if (resultType.isUninferredParameter() || resultType.isError()) return
|
||||||
|
|
||||||
val typeToIncorporate = incorporatePosition.initialConstraint.b
|
assert(!resultType.contains { it.typeConstructor() is TypeVariableTypeConstructor })
|
||||||
|
|
||||||
if (typeToIncorporate.isUninferredParameter() || typeToIncorporate.isError()) return
|
|
||||||
|
|
||||||
constraintIncorporator.incorporateIntoOtherConstraints(
|
constraintIncorporator.incorporateIntoOtherConstraints(
|
||||||
typeCheckerContext,
|
typeCheckerContext,
|
||||||
incorporatePosition.from.variable,
|
fixingTypeVariable,
|
||||||
Constraint(
|
Constraint(EQUALITY, resultType, incorporatePosition, derivedFrom = emptySet(), isNullabilityConstraint = false)
|
||||||
EQUALITY,
|
|
||||||
typeToIncorporate,
|
|
||||||
incorporatePosition,
|
|
||||||
derivedFrom = setOf(),
|
|
||||||
isNullabilityConstraint = false
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,13 +169,25 @@ class ConstraintInjector(
|
|||||||
private fun Context.isAllowedType(type: KotlinTypeMarker) =
|
private fun Context.isAllowedType(type: KotlinTypeMarker) =
|
||||||
type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
|
type.typeDepth() <= maxTypeDepthFromInitialConstraints + ALLOWED_DEPTH_DELTA_FOR_INCORPORATION
|
||||||
|
|
||||||
private inner class TypeCheckerContext(
|
private inner class TypeCheckerContext(val c: Context, val position: IncorporationConstraintPosition) :
|
||||||
val c: Context,
|
AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c {
|
||||||
val position: IncorporationConstraintPosition,
|
private val newPossibleConstraints = mutableSetOf<Pair<TypeVariableMarker, Constraint>>()
|
||||||
val baseLowerType: KotlinTypeMarker,
|
|
||||||
val baseUpperType: KotlinTypeMarker,
|
private var baseLowerType = position.initialConstraint.a
|
||||||
val addPossibleNewConstraints: (TypeVariableMarker, Constraint) -> Unit
|
private var baseUpperType = position.initialConstraint.b
|
||||||
) : AbstractTypeCheckerContextForConstraintSystem(), ConstraintIncorporator.Context, TypeSystemInferenceExtensionContext by c {
|
|
||||||
|
fun extractAllConstraints(): Set<Pair<TypeVariableMarker, Constraint>> {
|
||||||
|
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)
|
val baseContext: AbstractTypeCheckerContext = newBaseTypeCheckerContext(isErrorTypeEqualsToAnything, isStubTypeEqualsToAnything)
|
||||||
|
|
||||||
@@ -333,7 +342,8 @@ class ConstraintInjector(
|
|||||||
isNullabilityConstraint = isNullabilityConstraint,
|
isNullabilityConstraint = isNullabilityConstraint,
|
||||||
inputTypePositionBeforeIncorporation = inputTypePosition
|
inputTypePositionBeforeIncorporation = inputTypePosition
|
||||||
)
|
)
|
||||||
addPossibleNewConstraints(typeVariable, newConstraint)
|
|
||||||
|
newPossibleConstraints.add(typeVariable to newConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val allTypeVariablesWithConstraints: Collection<VariableWithConstraints>
|
override val allTypeVariablesWithConstraints: Collection<VariableWithConstraints>
|
||||||
|
|||||||
Reference in New Issue
Block a user