[FE] Prohibit expect fun interface to have non-fun actual counterpart
In K1 .isFun is always false for Java classes, so extra check is added for that. This is not needed for K2, because .isFun is true for all Java classes. Here it is not necessary to check that interface has only one method, because such check will be done in the place where interface implementation is created. ^KT-39362 Fixed
This commit is contained in:
committed by
Space Team
parent
59d126abc5
commit
456d3e0f42
+6
@@ -414,6 +414,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectFunInterface.kt")
|
||||
public void testExpectFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("explicitConstructorDelegation.kt")
|
||||
public void testExplicitConstructorDelegation() throws Exception {
|
||||
|
||||
+6
@@ -414,6 +414,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectFunInterface.kt")
|
||||
public void testExpectFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("explicitConstructorDelegation.kt")
|
||||
public void testExplicitConstructorDelegation() throws Exception {
|
||||
|
||||
+3
@@ -123,6 +123,9 @@ object FirExpectActualResolver {
|
||||
if (!equalBy(expectClassSymbol, actualClass) { listOf(it.isCompanion, it.isInner, it.isInline /*|| it.isValue*/) }) {
|
||||
return ExpectActualCompatibility.Incompatible.ClassModifiers
|
||||
}
|
||||
if (expectClassSymbol.isFun && !actualClass.isFun) {
|
||||
return ExpectActualCompatibility.Incompatible.FunInterfaceModifier
|
||||
}
|
||||
|
||||
val expectTypeParameterSymbols = expectClassSymbol.typeParameterSymbols
|
||||
val actualTypeParameterSymbols = actualClass.typeParameterSymbols
|
||||
|
||||
+2
-1
@@ -90,7 +90,8 @@ object ClassicPositioningStrategies {
|
||||
ExpectActualCompatibility.Incompatible.FunctionModifiersNotSubset,
|
||||
ExpectActualCompatibility.Incompatible.PropertyLateinitModifier,
|
||||
ExpectActualCompatibility.Incompatible.PropertyConstModifier,
|
||||
ExpectActualCompatibility.Incompatible.ClassModifiers -> {
|
||||
ExpectActualCompatibility.Incompatible.ClassModifiers,
|
||||
ExpectActualCompatibility.Incompatible.FunInterfaceModifier -> {
|
||||
element.modifierList
|
||||
}
|
||||
ExpectActualCompatibility.Incompatible.PropertyKind -> {
|
||||
|
||||
+7
@@ -387,6 +387,9 @@ object ExpectedActualResolver {
|
||||
if (a.kind != b.kind) return Incompatible.ClassKind
|
||||
|
||||
if (!equalBy(a, b) { listOf(it.isCompanionObject, it.isInner, it.isInline || it.isValue) }) return Incompatible.ClassModifiers
|
||||
if (a.isFun && !b.isFun && b.isNotJavaSamInterface()) {
|
||||
return Incompatible.FunInterfaceModifier
|
||||
}
|
||||
|
||||
val aTypeParams = a.declaredTypeParameters
|
||||
val bTypeParams = b.declaredTypeParameters
|
||||
@@ -563,3 +566,7 @@ fun DeclarationDescriptor.findActuals(inModule: ModuleDescriptor): List<MemberDe
|
||||
val DeclarationDescriptorWithSource.couldHaveASource: Boolean
|
||||
get() = this.source.containingFile != SourceFile.NO_SOURCE_FILE ||
|
||||
this is DeserializedDescriptor
|
||||
|
||||
private fun ClassDescriptor.isNotJavaSamInterface(): Boolean {
|
||||
return isDefinitelyNotSamInterface || defaultFunctionTypeForSamInterface == null
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
expect fun interface F1 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F2 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F3 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect interface F4 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F5 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F6 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
|
||||
actual fun interface F1 {
|
||||
actual fun run()
|
||||
}
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual interface F2 {
|
||||
actual fun run()
|
||||
}<!>
|
||||
|
||||
actual typealias F3 = java.lang.Runnable
|
||||
|
||||
actual fun interface F4 {
|
||||
actual fun run()
|
||||
}
|
||||
|
||||
fun interface F5Typealias {
|
||||
fun run()
|
||||
}
|
||||
|
||||
actual typealias F5 = F5Typealias
|
||||
|
||||
interface F6Typealias {
|
||||
fun run()
|
||||
}
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual typealias F6 = F6Typealias<!>
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
expect fun interface F1 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F2 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F3 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect interface F4 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F5 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface F6 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
|
||||
actual fun interface F1 {
|
||||
actual fun run()
|
||||
}
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual<!> interface F2 {
|
||||
actual fun run()
|
||||
}
|
||||
|
||||
actual typealias F3 = java.lang.Runnable
|
||||
|
||||
actual fun interface F4 {
|
||||
actual fun run()
|
||||
}
|
||||
|
||||
fun interface F5Typealias {
|
||||
fun run()
|
||||
}
|
||||
|
||||
actual typealias F5 = F5Typealias
|
||||
|
||||
interface F6Typealias {
|
||||
fun run()
|
||||
}
|
||||
|
||||
<!ACTUAL_WITHOUT_EXPECT!>actual<!> typealias F6 = F6Typealias
|
||||
@@ -19,3 +19,11 @@ expect class C4<F>
|
||||
|
||||
|
||||
expect abstract class ExtendsNumber : Number
|
||||
|
||||
expect fun interface FunInterface {
|
||||
fun run()
|
||||
}
|
||||
|
||||
expect fun interface FunInterface2 {
|
||||
fun run()
|
||||
}
|
||||
|
||||
@@ -19,3 +19,13 @@ actual typealias C4<F> = C4Impl<F>
|
||||
class C4Impl<F : Number>
|
||||
|
||||
actual abstract class ExtendsNumber : Any()
|
||||
|
||||
actual interface FunInterface {
|
||||
actual fun run()
|
||||
}
|
||||
|
||||
interface FunInterface2Typealias {
|
||||
fun run()
|
||||
}
|
||||
|
||||
actual typealias FunInterface2 = FunInterface2Typealias
|
||||
@@ -113,3 +113,15 @@ The following declaration is incompatible because some supertypes are missing in
|
||||
|
||||
actual abstract class ExtendsNumber : Any()
|
||||
^
|
||||
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:23:1: error: actual interface 'FunInterface' has no corresponding expected declaration
|
||||
The following declaration is incompatible because actual declaration for fun expect interface is not a functional interface:
|
||||
public expect fun interface FunInterface
|
||||
|
||||
actual interface FunInterface {
|
||||
^
|
||||
compiler/testData/multiplatform/incompatibleClasses/jvm.kt:31:1: error: actual typealias 'FunInterface2' has no corresponding expected declaration
|
||||
The following declaration is incompatible because actual declaration for fun expect interface is not a functional interface:
|
||||
public expect fun interface FunInterface2
|
||||
|
||||
actual typealias FunInterface2 = FunInterface2Typealias
|
||||
^
|
||||
|
||||
Generated
+6
@@ -22193,6 +22193,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectFunInterface.kt")
|
||||
public void testExpectFunInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("explicitConstructorDelegation.kt")
|
||||
public void testExplicitConstructorDelegation() throws Exception {
|
||||
|
||||
+2
@@ -65,6 +65,8 @@ sealed class ExpectActualCompatibility<out D> {
|
||||
|
||||
object ClassModifiers : Incompatible<Nothing>("modifiers are different (companion, inner, inline)")
|
||||
|
||||
object FunInterfaceModifier : Incompatible<Nothing>("actual declaration for fun expect interface is not a functional interface")
|
||||
|
||||
object Supertypes : Incompatible<Nothing>("some supertypes are missing in the actual declaration")
|
||||
|
||||
class ClassScopes<D>(
|
||||
|
||||
Reference in New Issue
Block a user