From 4694a7963b3b73b06fcb163b2c84450334fa5ae4 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Fri, 18 Jan 2019 17:59:06 +0300 Subject: [PATCH] Allow actuals with more permissive visibility Allow non-virtual expects to have actuals with more permissive visibility. ^KT-19664 Fixed --- .../multiplatform/ExpectedActualResolver.kt | 16 +++++++++++++++- .../morePermissiveVisibilityOnActual.kt | 6 ++++-- .../morePermissiveVisibilityOnActual.txt | 2 ++ ...rePermissiveVisibilityOnActualViaTypeAlias.kt | 2 +- .../incompatibleCallables/output.txt | 6 ------ 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt index 15805fba5ef..c918d1840a0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectedActualResolver.kt @@ -262,7 +262,7 @@ object ExpectedActualResolver { if (!equalsBy(aTypeParams, bTypeParams, TypeParameterDescriptor::getName)) return Incompatible.TypeParameterNames if (!areCompatibleModalities(a.modality, b.modality)) return Incompatible.Modality - if (a.visibility != b.visibility) return Incompatible.Visibility + if (!areDeclarationsWithCompatibleVisibilities(a, b)) return Incompatible.Visibility areCompatibleTypeParameters(aTypeParams, bTypeParams, platformModule, substitutor).let { if (it != Compatible) return it } @@ -427,6 +427,20 @@ object ExpectedActualResolver { a == b } + private fun areDeclarationsWithCompatibleVisibilities( + a: CallableMemberDescriptor, + b: CallableMemberDescriptor + ): Boolean { + val compare = Visibilities.compare(a.visibility, b.visibility) + return if (a.isOverridable) { + // For overridable declarations visibility should match precisely, see KT-19664 + compare == 0 + } else { + // For non-overridable declarations actuals are allowed to have more permissive visibility + compare != null && compare <= 0 + } + } + private fun areCompatibleClassScopes( a: ClassDescriptor, diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.kt index 7381bc7a902..d1447a8d6aa 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.kt @@ -15,6 +15,7 @@ expect open class Container { protected fun protectedFun3() open internal fun openInternalFun() + open fun openPublicFun() } // MODULE: m2-jvm(m1-common) @@ -24,14 +25,15 @@ expect open class Container { actual open class Container { actual fun publicFun() {} // OK: public -> public - actual fun internalFun1() {} // OK: internal -> public + actual fun internalFun1() {} // OK: internal -> public actual internal fun internalFun2() {} // OK: internal -> internal - actual fun protectedFun1() {} // OK: protected -> public + actual fun protectedFun1() {} // OK: protected -> public actual protected fun protectedFun2() {} // OK: protected -> protected actual internal fun protectedFun3() {} // BAD: protected -> internal actual protected fun internalFun3() {} // BAD: internal -> protected actual open fun openInternalFun() {} // BAD: internal+open -> public + actual internal fun openPublicFun() {} // BAD: open+public -> internal } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.txt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.txt index 4bdb6ba879b..aad2f344e25 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.txt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActual.txt @@ -8,6 +8,7 @@ public open expect class Container { internal final expect fun internalFun2(): kotlin.Unit internal final expect fun internalFun3(): kotlin.Unit internal open expect fun openInternalFun(): kotlin.Unit + public open expect fun openPublicFun(): kotlin.Unit protected final expect fun protectedFun1(): kotlin.Unit protected final expect fun protectedFun2(): kotlin.Unit protected final expect fun protectedFun3(): kotlin.Unit @@ -27,6 +28,7 @@ public open actual class Container { internal final actual fun internalFun2(): kotlin.Unit protected final actual fun internalFun3(): kotlin.Unit public open actual fun openInternalFun(): kotlin.Unit + internal final actual fun openPublicFun(): kotlin.Unit public final actual fun protectedFun1(): kotlin.Unit protected final actual fun protectedFun2(): kotlin.Unit internal final actual fun protectedFun3(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt index cdbd2982deb..5a44875cda6 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt @@ -19,4 +19,4 @@ public class Foo { // FILE: jvm.kt -actual typealias Container = foo.Foo \ No newline at end of file +actual typealias Container = foo.Foo \ No newline at end of file diff --git a/compiler/testData/multiplatform/incompatibleCallables/output.txt b/compiler/testData/multiplatform/incompatibleCallables/output.txt index 139cfef8d9e..59beb40b009 100644 --- a/compiler/testData/multiplatform/incompatibleCallables/output.txt +++ b/compiler/testData/multiplatform/incompatibleCallables/output.txt @@ -125,12 +125,6 @@ The following declaration is incompatible because number of type parameters is d actual fun f7() {} ^ -compiler/testData/multiplatform/incompatibleCallables/jvm.kt:16:1: error: actual function 'f8' has no corresponding expected declaration -The following declaration is incompatible because visibility is different: - internal expect fun f8(): Unit - -public actual fun f8() {} -^ compiler/testData/multiplatform/incompatibleCallables/jvm.kt:17:1: error: actual function 'f10' has no corresponding expected declaration The following declaration is incompatible because visibility is different: public expect fun f10(): Unit