[NI] Add initial constraint to IncorporationConstraintPosition
This commit is contained in:
+3
-2
@@ -150,12 +150,13 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
when (diagnostic.javaClass) {
|
||||
NewConstraintError::class.java -> {
|
||||
val constraintError = diagnostic as NewConstraintError
|
||||
(constraintError.position as? ArgumentConstraintPosition)?.let {
|
||||
val position = constraintError.position.from
|
||||
(position as? ArgumentConstraintPosition)?.let {
|
||||
val expression = it.argument.psiExpression ?: return
|
||||
if (reportConstantTypeMismatch(constraintError, expression)) return
|
||||
trace.report(Errors.TYPE_MISMATCH.on(expression, constraintError.upperType, constraintError.lowerType))
|
||||
}
|
||||
(constraintError.position as? ExplicitTypeParameterConstraintPosition)?.let {
|
||||
(position as? ExplicitTypeParameterConstraintPosition)?.let {
|
||||
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
|
||||
trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, constraintError.upperType, constraintError.lowerType))
|
||||
}
|
||||
|
||||
+15
-18
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.types.TypeApproximator
|
||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.CaptureStatus
|
||||
@@ -40,26 +38,26 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
|
||||
|
||||
fun getConstraintsForVariable(typeVariable: NewTypeVariable): Collection<Constraint>
|
||||
|
||||
fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: IncorporationConstraintPosition)
|
||||
fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType)
|
||||
}
|
||||
|
||||
// \alpha is typeVariable, \beta -- other type variable registered in ConstraintStorage
|
||||
fun incorporate(c: Context, typeVariable: NewTypeVariable, constraint: Constraint, position: IncorporationConstraintPosition) {
|
||||
fun incorporate(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
// we shouldn't incorporate recursive constraint -- It is too dangerous
|
||||
if (constraint.type.contains { it.constructor == typeVariable.freshTypeConstructor }) return
|
||||
|
||||
directWithVariable(c, typeVariable, constraint, position)
|
||||
otherInsideMyConstraint(c, typeVariable, constraint, position)
|
||||
insideOtherConstraint(c, typeVariable, constraint, position)
|
||||
directWithVariable(c, typeVariable, constraint)
|
||||
otherInsideMyConstraint(c, typeVariable, constraint)
|
||||
insideOtherConstraint(c, typeVariable, constraint)
|
||||
}
|
||||
|
||||
// A <:(=) \alpha <:(=) B => A <: B
|
||||
private fun directWithVariable(c: Context, typeVariable: NewTypeVariable, constraint: Constraint, position: IncorporationConstraintPosition) {
|
||||
private fun directWithVariable(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
// \alpha <: constraint.type
|
||||
if (constraint.kind != ConstraintKind.LOWER) {
|
||||
c.getConstraintsForVariable(typeVariable).forEach {
|
||||
if (it.kind != ConstraintKind.UPPER) {
|
||||
c.addNewIncorporatedConstraint(it.type, constraint.type, position)
|
||||
c.addNewIncorporatedConstraint(it.type, constraint.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,14 +66,14 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
|
||||
if (constraint.kind != ConstraintKind.UPPER) {
|
||||
c.getConstraintsForVariable(typeVariable).forEach {
|
||||
if (it.kind != ConstraintKind.LOWER) {
|
||||
c.addNewIncorporatedConstraint(constraint.type, it.type, position)
|
||||
c.addNewIncorporatedConstraint(constraint.type, it.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// \alpha <: Inv<\beta>, \beta <: Number => \alpha <: Inv<out Number>
|
||||
private fun otherInsideMyConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint, position: IncorporationConstraintPosition) {
|
||||
private fun otherInsideMyConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
val otherInMyConstraint = SmartSet.create<NewTypeVariable>()
|
||||
constraint.type.contains {
|
||||
otherInMyConstraint.addIfNotNull(c.getTypeVariable(it.constructor))
|
||||
@@ -86,19 +84,19 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
|
||||
// to avoid ConcurrentModificationException
|
||||
val otherConstraints = ArrayList(c.getConstraintsForVariable(otherTypeVariable))
|
||||
for (otherConstraint in otherConstraints) {
|
||||
generateNewConstraint(c, typeVariable, constraint, otherTypeVariable, otherConstraint, position)
|
||||
generateNewConstraint(c, typeVariable, constraint, otherTypeVariable, otherConstraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// \alpha <: Number, \beta <: Inv<\alpha> => \beta <: Inv<out Number>
|
||||
private fun insideOtherConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint, position: IncorporationConstraintPosition) {
|
||||
private fun insideOtherConstraint(c: Context, typeVariable: NewTypeVariable, constraint: Constraint) {
|
||||
for (typeVariableWithConstraint in c.allTypeVariablesWithConstraints) {
|
||||
val constraintsWhichConstraintMyVariable = typeVariableWithConstraint.constraints.filter {
|
||||
it.type.contains { it.constructor == typeVariable.freshTypeConstructor }
|
||||
}
|
||||
constraintsWhichConstraintMyVariable.forEach {
|
||||
generateNewConstraint(c, typeVariableWithConstraint.typeVariable, it, typeVariable, constraint, position)
|
||||
generateNewConstraint(c, typeVariableWithConstraint.typeVariable, it, typeVariable, constraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,8 +106,7 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
|
||||
targetVariable: NewTypeVariable,
|
||||
baseConstraint: Constraint,
|
||||
otherVariable: NewTypeVariable,
|
||||
otherConstraint: Constraint,
|
||||
position: IncorporationConstraintPosition
|
||||
otherConstraint: Constraint
|
||||
) {
|
||||
val typeForApproximation = when (otherConstraint.kind) {
|
||||
ConstraintKind.EQUALITY -> {
|
||||
@@ -134,10 +131,10 @@ class ConstraintIncorporator(val typeApproximator: TypeApproximator) {
|
||||
}
|
||||
|
||||
if (baseConstraint.kind != ConstraintKind.UPPER) {
|
||||
c.addNewIncorporatedConstraint(approximateCapturedTypes(typeForApproximation, toSuper = false), targetVariable.defaultType, position)
|
||||
c.addNewIncorporatedConstraint(approximateCapturedTypes(typeForApproximation, toSuper = false), targetVariable.defaultType)
|
||||
}
|
||||
if (baseConstraint.kind != ConstraintKind.LOWER) {
|
||||
c.addNewIncorporatedConstraint(targetVariable.defaultType, approximateCapturedTypes(typeForApproximation, toSuper = true), position)
|
||||
c.addNewIncorporatedConstraint(targetVariable.defaultType, approximateCapturedTypes(typeForApproximation, toSuper = true))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-11
@@ -40,25 +40,28 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
}
|
||||
|
||||
fun addInitialSubtypeConstraint(c: Context, lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) {
|
||||
c.addInitialConstraint(InitialConstraint(lowerType, upperType, ConstraintKind.UPPER, position))
|
||||
val initialConstraint = InitialConstraint(lowerType, upperType, ConstraintKind.UPPER, position)
|
||||
val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint)
|
||||
c.addInitialConstraint(initialConstraint)
|
||||
updateAllowedTypeDepth(c, lowerType)
|
||||
updateAllowedTypeDepth(c, upperType)
|
||||
addSubTypeConstraintAndIncorporateIt(c, lowerType, upperType, position)
|
||||
addSubTypeConstraintAndIncorporateIt(c, lowerType, upperType, incorporationPosition)
|
||||
}
|
||||
|
||||
fun addInitialEqualityConstraint(c: Context, a: UnwrappedType, b: UnwrappedType, position: ConstraintPosition) {
|
||||
c.addInitialConstraint(InitialConstraint(a, b, ConstraintKind.EQUALITY, position))
|
||||
val initialConstraint = InitialConstraint(a, b, ConstraintKind.EQUALITY, position)
|
||||
val incorporationPosition = IncorporationConstraintPosition(position, initialConstraint)
|
||||
c.addInitialConstraint(initialConstraint)
|
||||
updateAllowedTypeDepth(c, a)
|
||||
updateAllowedTypeDepth(c, b)
|
||||
addSubTypeConstraintAndIncorporateIt(c, a, b, position)
|
||||
addSubTypeConstraintAndIncorporateIt(c, b, a, position)
|
||||
addSubTypeConstraintAndIncorporateIt(c, a, b, incorporationPosition)
|
||||
addSubTypeConstraintAndIncorporateIt(c, b, a, incorporationPosition)
|
||||
}
|
||||
|
||||
|
||||
private fun addSubTypeConstraintAndIncorporateIt(c: Context, lowerType: UnwrappedType, upperType: UnwrappedType, position: ConstraintPosition) {
|
||||
val incorporatePosition = IncorporationConstraintPosition(position)
|
||||
private fun addSubTypeConstraintAndIncorporateIt(c: Context, lowerType: UnwrappedType, upperType: UnwrappedType, incorporatePosition: IncorporationConstraintPosition) {
|
||||
val possibleNewConstraints = Stack<Pair<NewTypeVariable, Constraint>>()
|
||||
val typeCheckerContext = TypeCheckerContext(c, position, lowerType, upperType, possibleNewConstraints)
|
||||
val typeCheckerContext = TypeCheckerContext(c, incorporatePosition, lowerType, upperType, possibleNewConstraints)
|
||||
typeCheckerContext.runIsSubtypeOf(lowerType, upperType)
|
||||
|
||||
while (possibleNewConstraints.isNotEmpty()) {
|
||||
@@ -67,7 +70,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
|
||||
// it is important, that we add constraint here(not inside TypeCheckerContext), because inside incorporation we read constraints
|
||||
constraints.addConstraint(constraint)?.let {
|
||||
constraintIncorporator.incorporate(typeCheckerContext, typeVariable, it, incorporatePosition)
|
||||
constraintIncorporator.incorporate(typeCheckerContext, typeVariable, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +97,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
|
||||
private inner class TypeCheckerContext(
|
||||
val c: Context,
|
||||
val position: ConstraintPosition,
|
||||
val position: IncorporationConstraintPosition,
|
||||
val baseLowerType: UnwrappedType,
|
||||
val baseUpperType: UnwrappedType,
|
||||
val possibleNewConstraints: MutableList<Pair<NewTypeVariable, Constraint>> = ArrayList()
|
||||
@@ -159,7 +162,7 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
}
|
||||
|
||||
// from ConstraintIncorporator.Context
|
||||
override fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType, position: IncorporationConstraintPosition) {
|
||||
override fun addNewIncorporatedConstraint(lowerType: UnwrappedType, upperType: UnwrappedType) {
|
||||
if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) {
|
||||
runIsSubtypeOf(lowerType, upperType)
|
||||
}
|
||||
|
||||
+3
-3
@@ -40,15 +40,15 @@ class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintP
|
||||
override fun toString() = "Fix variable $variable"
|
||||
}
|
||||
|
||||
class IncorporationConstraintPosition(val from: ConstraintPosition) : ConstraintPosition() {
|
||||
override fun toString() = "Incorporate $from"
|
||||
class IncorporationConstraintPosition(val from: ConstraintPosition, val initialConstraint: InitialConstraint) : ConstraintPosition() {
|
||||
override fun toString() = "Incorporate $initialConstraint from position $from"
|
||||
}
|
||||
|
||||
@Deprecated("Should be used only in SimpleConstraintSystemImpl")
|
||||
object SimpleConstraintSystemConstraintPosition : ConstraintPosition()
|
||||
|
||||
|
||||
class NewConstraintError(val lowerType: UnwrappedType, val upperType: UnwrappedType, val position: ConstraintPosition):
|
||||
class NewConstraintError(val lowerType: UnwrappedType, val upperType: UnwrappedType, val position: IncorporationConstraintPosition):
|
||||
KotlinCallDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.constraintError(this)
|
||||
}
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ enum class ConstraintKind {
|
||||
class Constraint(
|
||||
val kind: ConstraintKind,
|
||||
val type: UnwrappedType, // flexible types here is allowed
|
||||
val position: ConstraintPosition,
|
||||
val position: IncorporationConstraintPosition,
|
||||
val typeHashCode: Int = type.hashCode()
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
||||
Reference in New Issue
Block a user