Allow actuals with more permissive visibility

Allow non-virtual expects to have actuals with more permissive
visibility.

^KT-19664 Fixed
This commit is contained in:
Dmitry Savvinov
2019-01-18 17:59:06 +03:00
parent 0338753c11
commit 4694a7963b
5 changed files with 22 additions and 10 deletions
@@ -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,
@@ -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 <!ACTUAL_WITHOUT_EXPECT!>internalFun1<!>() {} // OK: internal -> public
actual fun internalFun1() {} // OK: internal -> public
actual internal fun internalFun2() {} // OK: internal -> internal
actual fun <!ACTUAL_WITHOUT_EXPECT!>protectedFun1<!>() {} // OK: protected -> public
actual fun protectedFun1() {} // OK: protected -> public
actual protected fun protectedFun2() {} // OK: protected -> protected
actual <!ACTUAL_WITHOUT_EXPECT!>internal<!> fun protectedFun3() {} // BAD: protected -> internal
actual <!ACTUAL_WITHOUT_EXPECT!>protected<!> fun internalFun3() {} // BAD: internal -> protected
actual open fun <!ACTUAL_WITHOUT_EXPECT!>openInternalFun<!>() {} // BAD: internal+open -> public
actual internal fun <!ACTUAL_WITHOUT_EXPECT!>openPublicFun<!>() {} // BAD: open+public -> internal
}
@@ -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
@@ -19,4 +19,4 @@ public class Foo {
// FILE: jvm.kt
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Container<!> = foo.Foo
actual typealias Container = foo.Foo
@@ -125,12 +125,6 @@ The following declaration is incompatible because number of type parameters is d
actual fun <K, V> 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