Fold lower constraints like (T!!..T) and (T..T?) into the latter one
#KT-41149 Fixed
This commit is contained in:
+57
-6
@@ -8,8 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.model
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.trimToSize
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
@@ -49,6 +48,7 @@ class MutableVariableWithConstraints private constructor(
|
||||
|
||||
// return new actual constraint, if this constraint is new
|
||||
fun addConstraint(constraint: Constraint): Constraint? {
|
||||
val isLowerAndFlexibleTypeWithDefNotNullLowerBound = constraint.isLowerAndFlexibleTypeWithDefNotNullLowerBound()
|
||||
|
||||
for (previousConstraint in constraints) {
|
||||
if (previousConstraint.typeHashCode == constraint.typeHashCode
|
||||
@@ -75,12 +75,23 @@ class MutableVariableWithConstraints private constructor(
|
||||
return actualConstraint
|
||||
}
|
||||
}
|
||||
|
||||
if (isLowerAndFlexibleTypeWithDefNotNullLowerBound &&
|
||||
previousConstraint.isStrongerThanLowerAndFlexibleTypeWithDefNotNullLowerBound(constraint)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
mutableConstraints.add(constraint)
|
||||
if (simplifiedConstraints != null && simplifiedConstraints !== mutableConstraints) {
|
||||
simplifiedConstraints!!.add(constraint)
|
||||
}
|
||||
|
||||
if (simplifiedConstraints != null && isLowerAndFlexibleTypeWithDefNotNullLowerBound) {
|
||||
simplifiedConstraints = null
|
||||
}
|
||||
|
||||
return constraint
|
||||
}
|
||||
|
||||
@@ -114,10 +125,50 @@ class MutableVariableWithConstraints private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun SmartList<Constraint>.simplifyConstraints(): SmartList<Constraint> {
|
||||
val equalityConstraints =
|
||||
filter { it.kind == ConstraintKind.EQUALITY }
|
||||
.groupBy { it.typeHashCode }
|
||||
private fun SmartList<Constraint>.simplifyConstraints(): SmartList<Constraint> =
|
||||
simplifyLowerConstraints().simplifyEqualityConstraints()
|
||||
|
||||
private fun SmartList<Constraint>.simplifyLowerConstraints(): SmartList<Constraint> {
|
||||
val usefulConstraints = SmartList<Constraint>()
|
||||
for (constraint in this) {
|
||||
if (!constraint.isLowerAndFlexibleTypeWithDefNotNullLowerBound()) {
|
||||
usefulConstraints.add(constraint)
|
||||
continue
|
||||
}
|
||||
|
||||
// Now we have to check that some constraint T!!.T? <: K is useless or not
|
||||
// If there is constraint T..T? <: K, then the original one (T!!.T?) is useless
|
||||
// This is so because CST(T..T?, T!!..T?) == CST(T..T?)
|
||||
|
||||
val thereIsStrongerConstraint = this.any { it.isStrongerThanLowerAndFlexibleTypeWithDefNotNullLowerBound(constraint) }
|
||||
|
||||
if (!thereIsStrongerConstraint) {
|
||||
usefulConstraints.add(constraint)
|
||||
}
|
||||
}
|
||||
|
||||
return usefulConstraints
|
||||
}
|
||||
|
||||
// Such constraint is applicable for simplification
|
||||
private fun Constraint.isLowerAndFlexibleTypeWithDefNotNullLowerBound(): Boolean =
|
||||
kind == ConstraintKind.LOWER && type is FlexibleType && type.lowerBound.isDefinitelyNotNullType
|
||||
|
||||
private fun Constraint.isStrongerThanLowerAndFlexibleTypeWithDefNotNullLowerBound(other: Constraint): Boolean {
|
||||
if (this === other) return false
|
||||
|
||||
if (typeHashCode != other.typeHashCode || kind == ConstraintKind.UPPER) return false
|
||||
if (type !is FlexibleType) return false
|
||||
|
||||
val otherFlexibleType = other.type as? FlexibleType ?: return false
|
||||
val otherLowerBound = otherFlexibleType.lowerBound as? DefinitelyNotNullType ?: return false
|
||||
val otherUpperBound = otherFlexibleType.upperBound
|
||||
|
||||
return type.lowerBound == otherLowerBound.original && type.upperBound == otherUpperBound
|
||||
}
|
||||
|
||||
private fun SmartList<Constraint>.simplifyEqualityConstraints(): SmartList<Constraint> {
|
||||
val equalityConstraints = filter { it.kind == ConstraintKind.EQUALITY }.groupBy { it.typeHashCode }
|
||||
return when {
|
||||
equalityConstraints.isEmpty() -> this
|
||||
else -> filterTo(SmartList()) { isUsefulConstraint(it, equalityConstraints) }
|
||||
|
||||
Reference in New Issue
Block a user