[FE] Fix TypeParameterUpperBounds incompatibility priority
^KT-60902 Fixed Review: https://jetbrains.team/p/kt/reviews/11039/timeline We should prioritize to return STRONG incompatibilities over WEAK incompatibilities. But this invariant broke in `areCompatibleCallables`, because `areCompatibleTypeParameters` returns incompatibilities of both types, and `areCompatibleTypeParameters` is called in WEAK incompatibilities section. The fix is to split `areCompatibleTypeParameters` into two functions: `areStrongIncompatibleTypeParameters` and `areWeakIncompatibleTypeParameters`. And call each of this function in appropriate `areCompatibleCallables` sections.
This commit is contained in:
+6
@@ -205,6 +205,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/kt58153.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/kt58153.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt60902.kt")
|
||||||
|
public void testKt60902() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/kt60902.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("manyImplMemberNotImplemented.kt")
|
@TestMetadata("manyImplMemberNotImplemented.kt")
|
||||||
public void testManyImplMemberNotImplemented() throws Exception {
|
public void testManyImplMemberNotImplemented() throws Exception {
|
||||||
|
|||||||
+6
@@ -205,6 +205,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/kt58153.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/kt58153.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt60902.kt")
|
||||||
|
public void testKt60902() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/kt60902.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("manyImplMemberNotImplemented.kt")
|
@TestMetadata("manyImplMemberNotImplemented.kt")
|
||||||
public void testManyImplMemberNotImplemented() throws Exception {
|
public void testManyImplMemberNotImplemented() throws Exception {
|
||||||
|
|||||||
+28
-7
@@ -298,6 +298,8 @@ object AbstractExpectActualCompatibilityChecker {
|
|||||||
return ExpectActualCompatibility.Compatible
|
return ExpectActualCompatibility.Compatible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ALL THE FOLLOWING ARE STRONG INCOMPATIBILITIES
|
||||||
|
|
||||||
if (expectDeclaration is FunctionSymbolMarker != actualDeclaration is FunctionSymbolMarker) {
|
if (expectDeclaration is FunctionSymbolMarker != actualDeclaration is FunctionSymbolMarker) {
|
||||||
return Incompatible.CallableKind
|
return Incompatible.CallableKind
|
||||||
}
|
}
|
||||||
@@ -345,6 +347,10 @@ object AbstractExpectActualCompatibilityChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
areStrongIncompatibleTypeParameters(expectedTypeParameters, actualTypeParameters, substitutor)?.let { return it }
|
||||||
|
|
||||||
|
// ALL THE FOLLOWING ARE WEAK INCOMPATIBILITIES
|
||||||
|
|
||||||
if (actualDeclaration.hasStableParameterNames && !equalsBy(expectedValueParameters, actualValueParameters) { it.name }) {
|
if (actualDeclaration.hasStableParameterNames && !equalsBy(expectedValueParameters, actualValueParameters) { it.name }) {
|
||||||
return Incompatible.ParameterNames
|
return Incompatible.ParameterNames
|
||||||
}
|
}
|
||||||
@@ -370,11 +376,7 @@ object AbstractExpectActualCompatibilityChecker {
|
|||||||
return Incompatible.Visibility
|
return Incompatible.Visibility
|
||||||
}
|
}
|
||||||
|
|
||||||
areCompatibleTypeParameters(expectedTypeParameters, actualTypeParameters, substitutor).let {
|
areWeakIncompatibleTypeParameters(expectedTypeParameters, actualTypeParameters)?.let { return it }
|
||||||
if (it != ExpectActualCompatibility.Compatible) {
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldCheckAbsenceOfDefaultParamsInActual) {
|
if (shouldCheckAbsenceOfDefaultParamsInActual) {
|
||||||
// "Default parameters in actual" check is required only for functions, because only functions can have parameters
|
// "Default parameters in actual" check is required only for functions, because only functions can have parameters
|
||||||
@@ -535,7 +537,18 @@ object AbstractExpectActualCompatibilityChecker {
|
|||||||
expectTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
expectTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
||||||
actualTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
actualTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
||||||
substitutor: TypeSubstitutorMarker,
|
substitutor: TypeSubstitutorMarker,
|
||||||
): ExpectActualCompatibility<*> {
|
): ExpectActualCompatibility<*> =
|
||||||
|
// We must prioritize to return STRONG incompatible over WEAK incompatible (because STRONG incompatibility allows to search for overloads)
|
||||||
|
areStrongIncompatibleTypeParameters(expectTypeParameterSymbols, actualTypeParameterSymbols, substitutor)
|
||||||
|
?: areWeakIncompatibleTypeParameters(expectTypeParameterSymbols, actualTypeParameterSymbols)
|
||||||
|
?: ExpectActualCompatibility.Compatible
|
||||||
|
|
||||||
|
context(ExpectActualMatchingContext<*>)
|
||||||
|
private fun areStrongIncompatibleTypeParameters(
|
||||||
|
expectTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
||||||
|
actualTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
||||||
|
substitutor: TypeSubstitutorMarker,
|
||||||
|
): Incompatible<*>? {
|
||||||
for (i in expectTypeParameterSymbols.indices) {
|
for (i in expectTypeParameterSymbols.indices) {
|
||||||
val expectBounds = expectTypeParameterSymbols[i].bounds
|
val expectBounds = expectTypeParameterSymbols[i].bounds
|
||||||
val actualBounds = actualTypeParameterSymbols[i].bounds
|
val actualBounds = actualTypeParameterSymbols[i].bounds
|
||||||
@@ -547,6 +560,14 @@ object AbstractExpectActualCompatibilityChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
context(ExpectActualMatchingContext<*>)
|
||||||
|
private fun areWeakIncompatibleTypeParameters(
|
||||||
|
expectTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
||||||
|
actualTypeParameterSymbols: List<TypeParameterSymbolMarker>,
|
||||||
|
): Incompatible<*>? {
|
||||||
if (!equalsBy(expectTypeParameterSymbols, actualTypeParameterSymbols) { it.variance }) {
|
if (!equalsBy(expectTypeParameterSymbols, actualTypeParameterSymbols) { it.variance }) {
|
||||||
return Incompatible.TypeParameterVariance
|
return Incompatible.TypeParameterVariance
|
||||||
}
|
}
|
||||||
@@ -560,7 +581,7 @@ object AbstractExpectActualCompatibilityChecker {
|
|||||||
return Incompatible.TypeParameterReified
|
return Incompatible.TypeParameterReified
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExpectActualCompatibility.Compatible
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
context(ExpectActualMatchingContext<*>)
|
context(ExpectActualMatchingContext<*>)
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
public expect fun <T : Comparable<T>> Array<out T>.foo()
|
||||||
|
|
||||||
|
// MODULE: m2-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
public actual fun <T : Comparable<T>> Array<out T>.foo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> Array<out T>.foo() {
|
||||||
|
}
|
||||||
Generated
+6
@@ -22884,6 +22884,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/kt58153.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/kt58153.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt60902.kt")
|
||||||
|
public void testKt60902() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/kt60902.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("manyImplMemberNotImplemented.kt")
|
@TestMetadata("manyImplMemberNotImplemented.kt")
|
||||||
public void testManyImplMemberNotImplemented() throws Exception {
|
public void testManyImplMemberNotImplemented() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user