[FIR] Allow actualization of expect classes by classes with wider visibility

^KT-59355 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-06-16 16:22:20 +03:00
committed by Space Team
parent 583aad2350
commit d972b78627
25 changed files with 257 additions and 4 deletions
@@ -175,6 +175,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
runTest("compiler/testData/diagnostics/tests/multiplatform/varSetterVisibility.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
@TestDataPath("$PROJECT_ROOT")
@@ -175,6 +175,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
runTest("compiler/testData/diagnostics/tests/multiplatform/varSetterVisibility.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
@TestDataPath("$PROJECT_ROOT")
@@ -33632,6 +33632,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
public void testValueClasses() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/valueClasses.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -33632,6 +33632,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
public void testValueClasses() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/valueClasses.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -40,6 +40,9 @@ class FirExpectActualMatchingContext(
override val enumConstructorsAreAlwaysCompatible: Boolean
get() = true
override val allowClassActualizationWithWiderVisibility: Boolean
get() = true
private fun CallableSymbolMarker.asSymbol(): FirCallableSymbol<*> = this as FirCallableSymbol<*>
private fun FunctionSymbolMarker.asSymbol(): FirFunctionSymbol<*> = this as FirFunctionSymbol<*>
private fun PropertySymbolMarker.asSymbol(): FirPropertySymbol = this as FirPropertySymbol
@@ -33,6 +33,9 @@ internal abstract class IrExpectActualMatchingContext(
val typeContext: IrTypeSystemContext,
val expectToActualClassMap: Map<ClassId, IrClassSymbol>
) : ExpectActualMatchingContext<IrSymbol>, TypeSystemContext by typeContext {
override val allowClassActualizationWithWiderVisibility: Boolean
get() = true
private inline fun <R> CallableSymbolMarker.processIr(
onFunction: (IrFunction) -> R,
onProperty: (IrProperty) -> R,
@@ -106,7 +106,7 @@ object AbstractExpectActualCompatibilityChecker {
return Incompatible.Modality
}
if (expectClassSymbol.visibility != actualClass.visibility) {
if (!areCompatibleClassVisibilities(expectClassSymbol, actualClass)) {
return Incompatible.Visibility
}
@@ -330,7 +330,7 @@ object AbstractExpectActualCompatibilityChecker {
return Incompatible.Modality
}
if (!areDeclarationsWithCompatibleVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility)) {
if (!areCompatibleCallableVisibilities(expectDeclaration.visibility, expectModality, actualDeclaration.visibility)) {
return Incompatible.Visibility
}
@@ -436,7 +436,7 @@ object AbstractExpectActualCompatibilityChecker {
Modality.SEALED to enumSetOf(Modality.SEALED),
)
private fun areDeclarationsWithCompatibleVisibilities(
private fun areCompatibleCallableVisibilities(
expectVisibility: Visibility,
expectModality: Modality?,
actualVisibility: Visibility,
@@ -451,6 +451,19 @@ object AbstractExpectActualCompatibilityChecker {
}
}
context(ExpectActualMatchingContext<*>)
private fun areCompatibleClassVisibilities(
expectClassSymbol: RegularClassSymbolMarker,
actualClassSymbol: RegularClassSymbolMarker,
): Boolean {
val expectVisibility = expectClassSymbol.visibility
val actualVisibility = actualClassSymbol.visibility
if (expectVisibility == actualVisibility) return true
if (!allowClassActualizationWithWiderVisibility) return false
val result = Visibilities.compare(actualVisibility, expectVisibility)
return result != null && result > 0
}
context(ExpectActualMatchingContext<*>)
private fun areCompatibleTypeParameters(
expectTypeParameterSymbols: List<TypeParameterSymbolMarker>,
@@ -525,7 +538,7 @@ object AbstractExpectActualCompatibilityChecker {
): Boolean {
val expectedSetter = expected.setter ?: return true
val actualSetter = actual.setter ?: return true
return areDeclarationsWithCompatibleVisibilities(expectedSetter.visibility, expectedSetter.modality, actualSetter.visibility)
return areCompatibleCallableVisibilities(expectedSetter.visibility, expectedSetter.modality, actualSetter.visibility)
}
// ---------------------------------------- Utils ----------------------------------------
@@ -39,6 +39,17 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
val enumConstructorsAreAlwaysCompatible: Boolean
get() = false
/**
* This flag determines, how visibilities for classes/typealiases will be matched
* - `false` means that visibilities should be identical
* - `true` means that visibility of actual class should be the same or wider comparing to expect visibility
* this means that following actualizations will be additionally allowed:
* - protected -> public
* - internal -> public
*/
val allowClassActualizationWithWiderVisibility: Boolean
get() = false
val RegularClassSymbolMarker.classId: ClassId
val TypeAliasSymbolMarker.classId: ClassId
val CallableSymbolMarker.callableId: CallableId
@@ -0,0 +1,49 @@
// IGNORE_BACKEND_K1: ANY
// IGNORE_REASON: KT-59355 is fixed only in K2
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_REASON: `JsName` in js.translator/testData/_commonFiles/testUtils.kt is invisible for some reason
// IGNORE_BACKEND: WASM
// IGNORE_REASON: wasm tests don't support IGNORE_BACKEND_K1 directive
// LANGUAGE: +MultiPlatformProjects
// ISSUE: KT-59355
// MODULE: common
// FILE: common.kt
internal expect open class Some() {
protected class ProtectedNested() {
fun foo(): String
}
}
internal class SomeInheritor : Some() {
fun callFoo(): String {
return ProtectedNested().foo()
}
}
internal expect open class Other() {
fun bar(): String
}
fun commonBox(): String {
val x = SomeInheritor().callFoo()
val y = Other().bar()
return x + y
}
// MODULE: platform-jvm()()(common)
// FILE: main.kt
public actual open class Some actual constructor() {
public actual class ProtectedNested actual constructor() {
actual fun foo(): String = "O"
}
}
public open class PlatformOther {
fun bar(): String = "K"
}
internal actual typealias Other = PlatformOther
fun box(): String = commonBox()
@@ -0,0 +1,34 @@
// ISSUE: KT-59355
// MODULE: common
internal expect open class Some {
protected class ProtectedNested
internal class InternalNested
public fun publicFun()
internal fun internalFun()
protected fun protectedFun()
}
internal expect open class Other {
protected class ProtectedNested
internal class InternalNested
}
// MODULE: platform-jvm()()(common)
public actual open class Some { // should be allowed
public class ProtectedNested // should be allowed
public class InternalNested // should be allowed
public actual fun publicFun() {} // should be allowed
public actual fun internalFun() {} // should be allowed
public actual fun protectedFun() {} // should be allowed
}
public open class PlatformOther { // should be allowed
public class ProtectedNested // should be allowed
public class InternalNested // should be allowed
}
internal actual typealias Other = PlatformOther // should be allowed
@@ -0,0 +1,34 @@
// ISSUE: KT-59355
// MODULE: common
internal expect open class <!NO_ACTUAL_FOR_EXPECT!>Some<!> {
protected class ProtectedNested
internal class InternalNested
public fun publicFun()
internal fun internalFun()
protected fun protectedFun()
}
internal expect open class <!NO_ACTUAL_FOR_EXPECT!>Other<!> {
protected class ProtectedNested
internal class InternalNested
}
// MODULE: platform-jvm()()(common)
<!ACTUAL_WITHOUT_EXPECT!>public<!> actual open class Some { // should be allowed
<!ACTUAL_WITHOUT_EXPECT!>public<!> class <!ACTUAL_MISSING!>ProtectedNested<!> // should be allowed
<!ACTUAL_WITHOUT_EXPECT!>public<!> class <!ACTUAL_MISSING!>InternalNested<!> // should be allowed
public actual fun publicFun() {} // should be allowed
public actual fun internalFun() {} // should be allowed
public actual fun protectedFun() {} // should be allowed
}
public open class PlatformOther { // should be allowed
public class ProtectedNested // should be allowed
public class InternalNested // should be allowed
}
<!ACTUAL_WITHOUT_EXPECT!>internal<!> actual typealias Other = PlatformOther // should be allowed
@@ -22486,6 +22486,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/multiplatform/varSetterVisibility.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt");
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/defaultArguments")
@TestDataPath("$PROJECT_ROOT")
@@ -32072,6 +32072,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -33632,6 +33632,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testValueClasses() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/valueClasses.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -33632,6 +33632,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
public void testValueClasses() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/valueClasses.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -27349,6 +27349,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testNonExternalEquals() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/nonExternalEquals.kt");
}
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiplatform/k2/defaultArguments")
@@ -23432,6 +23432,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -23594,6 +23594,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -23594,6 +23594,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -23594,6 +23594,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -26666,6 +26666,12 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -27272,6 +27272,12 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -26364,6 +26364,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -26667,6 +26667,12 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@Test
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@Nested
@@ -20962,6 +20962,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
public void testRemoveExpectDeclarationsFromMetadata() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/removeExpectDeclarationsFromMetadata.kt");
}
@TestMetadata("widerVisibilityInActualClassifier.kt")
public void testWiderVisibilityInActualClassifier() throws Exception {
runTest("compiler/testData/codegen/box/multiplatform/k2/basic/widerVisibilityInActualClassifier.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/multiplatform/k2/defaultArguments")