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