Fold lower constraints like (T!!..T) and (T..T?) into the latter one
#KT-41149 Fixed
This commit is contained in:
Generated
+5
@@ -12632,6 +12632,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt")
|
||||||
|
public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/manyFlexibleTypeParametersFromJavaAndConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
||||||
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
||||||
|
|||||||
+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.inference.trimToSize
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||||
@@ -49,6 +48,7 @@ class MutableVariableWithConstraints private constructor(
|
|||||||
|
|
||||||
// return new actual constraint, if this constraint is new
|
// return new actual constraint, if this constraint is new
|
||||||
fun addConstraint(constraint: Constraint): Constraint? {
|
fun addConstraint(constraint: Constraint): Constraint? {
|
||||||
|
val isLowerAndFlexibleTypeWithDefNotNullLowerBound = constraint.isLowerAndFlexibleTypeWithDefNotNullLowerBound()
|
||||||
|
|
||||||
for (previousConstraint in constraints) {
|
for (previousConstraint in constraints) {
|
||||||
if (previousConstraint.typeHashCode == constraint.typeHashCode
|
if (previousConstraint.typeHashCode == constraint.typeHashCode
|
||||||
@@ -75,12 +75,23 @@ class MutableVariableWithConstraints private constructor(
|
|||||||
return actualConstraint
|
return actualConstraint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isLowerAndFlexibleTypeWithDefNotNullLowerBound &&
|
||||||
|
previousConstraint.isStrongerThanLowerAndFlexibleTypeWithDefNotNullLowerBound(constraint)
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutableConstraints.add(constraint)
|
mutableConstraints.add(constraint)
|
||||||
if (simplifiedConstraints != null && simplifiedConstraints !== mutableConstraints) {
|
if (simplifiedConstraints != null && simplifiedConstraints !== mutableConstraints) {
|
||||||
simplifiedConstraints!!.add(constraint)
|
simplifiedConstraints!!.add(constraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (simplifiedConstraints != null && isLowerAndFlexibleTypeWithDefNotNullLowerBound) {
|
||||||
|
simplifiedConstraints = null
|
||||||
|
}
|
||||||
|
|
||||||
return constraint
|
return constraint
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,10 +125,50 @@ class MutableVariableWithConstraints private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SmartList<Constraint>.simplifyConstraints(): SmartList<Constraint> {
|
private fun SmartList<Constraint>.simplifyConstraints(): SmartList<Constraint> =
|
||||||
val equalityConstraints =
|
simplifyLowerConstraints().simplifyEqualityConstraints()
|
||||||
filter { it.kind == ConstraintKind.EQUALITY }
|
|
||||||
.groupBy { it.typeHashCode }
|
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 {
|
return when {
|
||||||
equalityConstraints.isEmpty() -> this
|
equalityConstraints.isEmpty() -> this
|
||||||
else -> filterTo(SmartList()) { isUsefulConstraint(it, equalityConstraints) }
|
else -> filterTo(SmartList()) { isUsefulConstraint(it, equalityConstraints) }
|
||||||
|
|||||||
Vendored
+64
@@ -0,0 +1,64 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
|
// FILE: Combiner.java
|
||||||
|
|
||||||
|
public class Combiner {
|
||||||
|
public static <T1, T2, T3, T4, T5, R> void combine(
|
||||||
|
Inv<? extends T1> source1, Inv<? extends T2> source2,
|
||||||
|
Inv<? extends T3> source3, Inv<? extends T4> source4,
|
||||||
|
Inv<? extends T5> source5,
|
||||||
|
Function5<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? extends R> combiner
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Function5.java
|
||||||
|
|
||||||
|
public interface Function5<T1, T2, T3, T4, T5, R> {
|
||||||
|
R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Test.kt
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, T5, R> kCombine(
|
||||||
|
s1: Inv<out T1>, s2: Inv<out T2>, s3: Inv<out T3>, s4: Inv<out T4>, s5: Inv<out T5>,
|
||||||
|
f: Function5<in T1, in T2, in T3, in T4, in T5, out R>
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Quantiple<out T1, out T2, out T3, out T4, out T5>(
|
||||||
|
val first: T1,
|
||||||
|
val second: T2,
|
||||||
|
val third: T3,
|
||||||
|
val fourth: T4,
|
||||||
|
val fifth: T5
|
||||||
|
)
|
||||||
|
|
||||||
|
fun <K1, K2, K3, K4, K5> materialize(): (K1, K2, K3, K4, K5) -> Quantiple<K1, K2, K3, K4, K5> = { _, _, _, _, _ -> TODO() }
|
||||||
|
|
||||||
|
class Inv<T>
|
||||||
|
|
||||||
|
fun <P1, P2, P3, P4, P5> test(
|
||||||
|
p1: Inv<out P1>, p2: Inv<out P2>, p3: Inv<out P3>, p4: Inv<out P4>, p5: Inv<out P5>
|
||||||
|
) {
|
||||||
|
Combiner.combine(
|
||||||
|
p1, p2, p3, p4, p5,
|
||||||
|
materialize()
|
||||||
|
)
|
||||||
|
|
||||||
|
Combiner.combine(
|
||||||
|
p1, p2, p3, p4, p5,
|
||||||
|
::Quantiple
|
||||||
|
)
|
||||||
|
|
||||||
|
kCombine(
|
||||||
|
p1, p2, p3, p4, p5,
|
||||||
|
materialize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(Inv<Int>(), Inv<Byte>(), Inv<Short>(), Inv<Long>(), Inv<String>())
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -13857,6 +13857,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt")
|
||||||
|
public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/manyFlexibleTypeParametersFromJavaAndConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
||||||
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
||||||
|
|||||||
+5
@@ -13857,6 +13857,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt")
|
||||||
|
public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/manyFlexibleTypeParametersFromJavaAndConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
||||||
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
||||||
|
|||||||
+5
@@ -12632,6 +12632,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
runTest("compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("manyFlexibleTypeParametersFromJavaAndConversions.kt")
|
||||||
|
public void testManyFlexibleTypeParametersFromJavaAndConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inference/manyFlexibleTypeParametersFromJavaAndConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
@TestMetadata("noCoercionToUniForNullableLambdaReturnType.kt")
|
||||||
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
public void testNoCoercionToUniForNullableLambdaReturnType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
runTest("compiler/testData/codegen/box/inference/noCoercionToUniForNullableLambdaReturnType.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user