NI: Fix some unwanted exclusions constraints with remained corresponding optimization
This commit is contained in:
+48
-4
@@ -157,6 +157,11 @@ class ConstraintIncorporator(
|
|||||||
isSubtype: Boolean
|
isSubtype: Boolean
|
||||||
) {
|
) {
|
||||||
if (targetVariable in getNestedTypeVariables(newConstraint)) return
|
if (targetVariable in getNestedTypeVariables(newConstraint)) return
|
||||||
|
|
||||||
|
val isUsefulForNullabilityConstraint =
|
||||||
|
isPotentialUsefulNullabilityConstraint(newConstraint, otherConstraint.type, otherConstraint.kind)
|
||||||
|
|
||||||
|
if (!isUsefulForNullabilityConstraint && !containsConstrainingTypeWithoutProjection(newConstraint, otherConstraint)) return
|
||||||
if (trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(
|
if (trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(
|
||||||
baseConstraint, otherConstraint, newConstraint, isSubtype
|
baseConstraint, otherConstraint, newConstraint, isSubtype
|
||||||
)
|
)
|
||||||
@@ -172,6 +177,28 @@ class ConstraintIncorporator(
|
|||||||
addNewIncorporatedConstraint(targetVariable, newConstraint, ConstraintContext(kind, derivedFrom))
|
addNewIncorporatedConstraint(targetVariable, newConstraint, ConstraintContext(kind, derivedFrom))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.containsConstrainingTypeWithoutProjection(
|
||||||
|
newConstraint: KotlinTypeMarker,
|
||||||
|
otherConstraint: Constraint
|
||||||
|
): Boolean {
|
||||||
|
return getNestedArguments(newConstraint).any {
|
||||||
|
it.getType().typeConstructor() == otherConstraint.type.typeConstructor() && it.getVariance() == TypeVariance.INV
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Context.isPotentialUsefulNullabilityConstraint(
|
||||||
|
newConstraint: KotlinTypeMarker,
|
||||||
|
otherConstraint: KotlinTypeMarker,
|
||||||
|
kind: ConstraintKind
|
||||||
|
): Boolean {
|
||||||
|
val otherConstraintCanAddNullabilityToNewOne =
|
||||||
|
!newConstraint.isNullableType() && otherConstraint.isNullableType() && kind == ConstraintKind.LOWER
|
||||||
|
val newConstraintCanAddNullabilityToOtherOne =
|
||||||
|
newConstraint.isNullableType() && !otherConstraint.isNullableType() && kind == ConstraintKind.UPPER
|
||||||
|
|
||||||
|
return otherConstraintCanAddNullabilityToNewOne || newConstraintCanAddNullabilityToOtherOne
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.getNestedTypeVariables(type: KotlinTypeMarker): List<TypeVariableMarker> =
|
fun Context.getNestedTypeVariables(type: KotlinTypeMarker): List<TypeVariableMarker> =
|
||||||
getNestedArguments(type).mapNotNull { getTypeVariable(it.getType().typeConstructor()) }
|
getNestedArguments(type).mapNotNull { getTypeVariable(it.getType().typeConstructor()) }
|
||||||
|
|
||||||
@@ -189,19 +216,36 @@ class ConstraintIncorporator(
|
|||||||
|
|
||||||
private fun TypeSystemInferenceExtensionContext.getNestedArguments(type: KotlinTypeMarker): List<TypeArgumentMarker> {
|
private fun TypeSystemInferenceExtensionContext.getNestedArguments(type: KotlinTypeMarker): List<TypeArgumentMarker> {
|
||||||
val result = ArrayList<TypeArgumentMarker>()
|
val result = ArrayList<TypeArgumentMarker>()
|
||||||
|
|
||||||
val stack = ArrayDeque<TypeArgumentMarker>()
|
val stack = ArrayDeque<TypeArgumentMarker>()
|
||||||
|
|
||||||
|
when (type) {
|
||||||
|
is FlexibleType -> {
|
||||||
|
stack.push(createTypeArgument(type.lowerBound, TypeVariance.INV))
|
||||||
|
stack.push(createTypeArgument(type.upperBound, TypeVariance.INV))
|
||||||
|
}
|
||||||
|
else -> stack.push(createTypeArgument(type, TypeVariance.INV))
|
||||||
|
}
|
||||||
|
|
||||||
stack.push(createTypeArgument(type, TypeVariance.INV))
|
stack.push(createTypeArgument(type, TypeVariance.INV))
|
||||||
|
|
||||||
|
val addArgumentsToStack = { projectedType: KotlinTypeMarker ->
|
||||||
|
for (argumentIndex in 0 until projectedType.argumentsCount()) {
|
||||||
|
stack.add(projectedType.getArgument(argumentIndex))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
val typeProjection = stack.pop()
|
val typeProjection = stack.pop()
|
||||||
if (typeProjection.isStarProjection()) continue
|
if (typeProjection.isStarProjection()) continue
|
||||||
|
|
||||||
result.add(typeProjection)
|
result.add(typeProjection)
|
||||||
|
|
||||||
val projectedType = typeProjection.getType()
|
when (val projectedType = typeProjection.getType()) {
|
||||||
for (argumentIndex in 0 until projectedType.argumentsCount()) {
|
is FlexibleType -> {
|
||||||
stack.add(projectedType.getArgument(argumentIndex))
|
addArgumentsToStack(projectedType.lowerBound)
|
||||||
|
addArgumentsToStack(projectedType.upperBound)
|
||||||
|
}
|
||||||
|
else -> addArgumentsToStack(projectedType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
fun <T : Any> nullable(): T? = null
|
fun <T : Any> nullable(): T? = null
|
||||||
|
|
||||||
val value = nullable<Int>() <!NI;TYPE_MISMATCH!>?:<!> <!OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>nullable()<!>
|
val value = nullable<Int>() ?: <!OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>nullable()<!>
|
||||||
Reference in New Issue
Block a user