From 2682837fd7ae0d966d8ff8bf089d994abeb2c889 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 12 Oct 2017 12:05:59 +0200 Subject: [PATCH] Support 'expect final' -> 'actual open' for callables #KT-17944 --- .../ExpectedActualDeclarationChecker.kt | 9 ++++- .../headerClass/expectFinalActualOpen.kt | 27 +++++++++++++ .../headerClass/expectFinalActualOpen.txt | 39 +++++++++++++++++++ ...lityCheckForExplicitAndImplicitOverride.kt | 6 +-- .../checkers/DiagnosticsTestGenerated.java | 6 +++ .../DiagnosticsUsingJavacTestGenerated.java | 6 +++ 6 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt index fa5c5a081e4..e9e50139e13 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt @@ -397,7 +397,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { if (b.hasStableParameterNames() && !equalsBy(aParams, bParams, ValueParameterDescriptor::getName)) return Incompatible.ParameterNames if (!equalsBy(aTypeParams, bTypeParams, TypeParameterDescriptor::getName)) return Incompatible.TypeParameterNames - if (a.modality != b.modality) return Incompatible.Modality + if (!areCompatibleModalities(a.modality, b.modality)) return Incompatible.Modality if (a.visibility != b.visibility) return Incompatible.Visibility areCompatibleTypeParameters(aTypeParams, bTypeParams, platformModule, substitutor).let { if (it != Compatible) return it } @@ -535,7 +535,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { val bTypeParams = b.declaredTypeParameters if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount - if (a.modality != b.modality && !(a.modality == Modality.FINAL && b.modality == Modality.OPEN)) return Incompatible.Modality + if (!areCompatibleModalities(a.modality, b.modality)) return Incompatible.Modality if (a.visibility != b.visibility) return Incompatible.Visibility @@ -556,6 +556,11 @@ object ExpectedActualDeclarationChecker : DeclarationChecker { return Compatible } + private fun areCompatibleModalities(a: Modality, b: Modality): Boolean { + return a == Modality.FINAL && b == Modality.OPEN || + a == b + } + private fun areCompatibleClassScopes( a: ClassDescriptor, diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt new file mode 100644 index 00000000000..63088d416ac --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt @@ -0,0 +1,27 @@ +// !LANGUAGE: +MultiPlatformProjects +// MODULE: m1-common +// FILE: common.kt + +expect class Foo { + fun f() + val v: String +} + +expect class Bar { + fun g() +} + +// MODULE: m2-jvm(m1-common) +// FILE: jvm.kt + +actual open class Foo(actual open val v: String) { + actual open fun f() {} +} + +actual typealias Bar = JavaBar + +// FILE: JavaBar.java + +public class JavaBar { + public void g() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.txt new file mode 100644 index 00000000000..e602867ac9f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.txt @@ -0,0 +1,39 @@ +// -- Module: -- +package + +public final expect class Bar { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final expect fun g(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final expect class Foo { + public expect final val v: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final expect fun f(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + + +// -- Module: -- +package + +public open actual class Foo { + public constructor Foo(/*0*/ v: kotlin.String) + public actual open val v: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open actual fun f(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public open class JavaBar { + public constructor JavaBar() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun g(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} +public typealias Bar = JavaBar diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/modalityCheckForExplicitAndImplicitOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/modalityCheckForExplicitAndImplicitOverride.kt index 08f48fa58b9..71578189703 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/modalityCheckForExplicitAndImplicitOverride.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/modalityCheckForExplicitAndImplicitOverride.kt @@ -23,13 +23,13 @@ open class Open { } actual open class Foo1 : Open() { - override val x = super.x + override val x = super.x } -actual open class Foo2 : Open() +actual open class Foo2 : Open() open class WithFinal { val x = "42" } -actual open class Foo3 : WithFinal() \ No newline at end of file +actual open class Foo3 : WithFinal() diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 2594dbaa115..e5c95f6b46f 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -14139,6 +14139,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("expectFinalActualOpen.kt") + public void testExpectFinalActualOpen() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt"); + doTest(fileName); + } + @TestMetadata("explicitConstructorDelegation.kt") public void testExplicitConstructorDelegation() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/explicitConstructorDelegation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index f821af40d7a..584f3f19608 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -14139,6 +14139,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing doTest(fileName); } + @TestMetadata("expectFinalActualOpen.kt") + public void testExpectFinalActualOpen() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/expectFinalActualOpen.kt"); + doTest(fileName); + } + @TestMetadata("explicitConstructorDelegation.kt") public void testExplicitConstructorDelegation() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/explicitConstructorDelegation.kt");