From 7b8445f914cc9e62c0c7922b5e3ee2a6b72d714c Mon Sep 17 00:00:00 2001 From: Nikita Bobko Date: Thu, 14 Sep 2023 20:26:14 +0200 Subject: [PATCH] [FIR] 2/2 Support more wider actual member visibility, if the expect member is effectively final ^KT-61955 Fixed Introduce LV vs don't introduce LV: introduce LV: - K1 IDE and K2 project: IDE accurately shows compiler errors - K2 IDE and K1 project: There are cases when IDE shows red but in reality it's green don't introduce LV: - K1 IDE and K2 project: There are cases when IDE shows red but in reality it's green - K2 IDE and K1 project: There are cases when IDE shows green but in reality it's red --- ...DiagnosticsWithLightTreeTestGenerated.java | 30 +++++++++++++++++++ ...endMPPDiagnosticsWithPsiTestGenerated.java | 30 +++++++++++++++++++ .../calls/mpp/AbstractExpectActualChecker.kt | 17 +++++++++-- ...Visibility_expectIsEffectivelyFinal.fir.kt | 17 +++++++++++ ...iderVisibility_expectIsEffectivelyFinal.kt | 17 +++++++++++ ...y_expectIsEffectivelyFinal_fakeOverride.kt | 16 ++++++++++ ...EffectivelyFinal_oldLanguageVersion.fir.kt | 18 +++++++++++ ...ctIsEffectivelyFinal_oldLanguageVersion.kt | 18 +++++++++++ ...lity_expectSetterIsEffectivelyFinal.fir.kt | 19 ++++++++++++ ...sibility_expectSetterIsEffectivelyFinal.kt | 19 ++++++++++++ ...ctSetterIsEffectivelyFinal_fakeOverride.kt | 17 +++++++++++ .../test/runners/DiagnosticTestGenerated.java | 30 +++++++++++++++++++ .../kotlin/config/LanguageVersionSettings.kt | 1 + 13 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.fir.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.fir.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.fir.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.kt create mode 100644 compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java index 824a480aa0b..0cae76b8942 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java @@ -367,6 +367,36 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt"); } + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal.kt") + public void testWiderVisibility_expectIsEffectivelyFinal() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt") + public void testWiderVisibility_expectIsEffectivelyFinal_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt") + public void testWiderVisibility_expectIsEffectivelyFinal_oldLanguageVersion() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectSetterIsEffectivelyFinal.kt") + public void testWiderVisibility_expectSetterIsEffectivelyFinal() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt") + public void testWiderVisibility_expectSetterIsEffectivelyFinal_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java index ab023bde0be..58947fe1b99 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java @@ -367,6 +367,36 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt"); } + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal.kt") + public void testWiderVisibility_expectIsEffectivelyFinal() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt") + public void testWiderVisibility_expectIsEffectivelyFinal_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt") + public void testWiderVisibility_expectIsEffectivelyFinal_oldLanguageVersion() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectSetterIsEffectivelyFinal.kt") + public void testWiderVisibility_expectSetterIsEffectivelyFinal() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt") + public void testWiderVisibility_expectSetterIsEffectivelyFinal_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt index 938ac993372..e56a2aff79d 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.resolve.calls.mpp +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality @@ -360,6 +361,7 @@ object AbstractExpectActualChecker { if (!areCompatibleCallableVisibilities( expectDeclaration.visibility, expectModality, + expectContainingClass?.modality, actualDeclaration.visibility, languageVersionSettings ) @@ -404,7 +406,7 @@ object AbstractExpectActualChecker { getFunctionsIncompatibility(expectDeclaration, actualDeclaration)?.let { return it } expectDeclaration is PropertySymbolMarker && actualDeclaration is PropertySymbolMarker -> - getPropertiesIncompatibility(expectDeclaration, actualDeclaration, languageVersionSettings)?.let { return it } + getPropertiesIncompatibility(expectDeclaration, actualDeclaration, expectContainingClass, languageVersionSettings)?.let { return it } expectDeclaration is EnumEntrySymbolMarker && actualDeclaration is EnumEntrySymbolMarker -> { // do nothing, entries are matched only by name @@ -465,11 +467,17 @@ object AbstractExpectActualChecker { private fun areCompatibleCallableVisibilities( expectVisibility: Visibility, expectModality: Modality?, + expectContainingClassModality: Modality?, actualVisibility: Visibility, languageVersionSettings: LanguageVersionSettings, ): Boolean { val compare = Visibilities.compare(expectVisibility, actualVisibility) - return if (expectModality != Modality.FINAL) { + val effectiveModality = + when (languageVersionSettings.supportsFeature(LanguageFeature.SupportEffectivelyFinalInExpectActualVisibilityCheck)) { + true -> effectiveModality(expectModality, expectContainingClassModality) + false -> expectModality + } + return if (effectiveModality != Modality.FINAL) { // For overridable declarations visibility should match precisely, see KT-19664 compare == 0 } else { @@ -536,13 +544,14 @@ object AbstractExpectActualChecker { private fun getPropertiesIncompatibility( expected: PropertySymbolMarker, actual: PropertySymbolMarker, + expectContainingClass: RegularClassSymbolMarker?, languageVersionSettings: LanguageVersionSettings, ): ExpectActualCheckingCompatibility.Incompatible<*>? { return when { !equalBy(expected, actual) { p -> p.isVar } -> ExpectActualCheckingCompatibility.PropertyKind !equalBy(expected, actual) { p -> p.isLateinit } -> ExpectActualCheckingCompatibility.PropertyLateinitModifier expected.isConst && !actual.isConst -> ExpectActualCheckingCompatibility.PropertyConstModifier - !arePropertySettersWithCompatibleVisibilities(expected, actual, languageVersionSettings) -> + !arePropertySettersWithCompatibleVisibilities(expected, actual, expectContainingClass, languageVersionSettings) -> ExpectActualCheckingCompatibility.PropertySetterVisibility else -> null } @@ -552,6 +561,7 @@ object AbstractExpectActualChecker { private fun arePropertySettersWithCompatibleVisibilities( expected: PropertySymbolMarker, actual: PropertySymbolMarker, + expectContainingClass: RegularClassSymbolMarker?, languageVersionSettings: LanguageVersionSettings, ): Boolean { val expectedSetter = expected.setter ?: return true @@ -559,6 +569,7 @@ object AbstractExpectActualChecker { return areCompatibleCallableVisibilities( expectedSetter.visibility, expectedSetter.modality, + expectContainingClass?.modality, actualSetter.visibility, languageVersionSettings ) diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.fir.kt new file mode 100644 index 00000000000..3f8340a6a06 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + internal open fun foo() {} +} +expect class Foo : Base { + override fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + public actual override fun foo() { + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.kt new file mode 100644 index 00000000000..d0c521cc1b2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + internal open fun foo() {} +} +expect class Foo : Base { + override fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + public actual override fun foo() { + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt new file mode 100644 index 00000000000..4c9f8817383 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt @@ -0,0 +1,16 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +open class Base { + protected open fun foo() {} +} +expect class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + public override fun foo() { + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.fir.kt new file mode 100644 index 00000000000..4fd183a538b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.fir.kt @@ -0,0 +1,18 @@ +// LANGUAGE: -SupportEffectivelyFinalInExpectActualVisibilityCheck +// MODULE: m1-common +// FILE: common.kt + +open class Base { + internal open fun foo() {} +} +expect class Foo : Base { + override fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + public actual override fun foo() { + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt new file mode 100644 index 00000000000..c598c494461 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt @@ -0,0 +1,18 @@ +// LANGUAGE: -SupportEffectivelyFinalInExpectActualVisibilityCheck +// MODULE: m1-common +// FILE: common.kt + +open class Base { + internal open fun foo() {} +} +expect class Foo : Base { + override fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + public actual override fun foo() { + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.fir.kt new file mode 100644 index 00000000000..506dac88783 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.fir.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open var foo: Int = 2 + internal set +} +expect class Foo : Base { + override var foo: Int + internal set +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + actual override var foo: Int = 2 + public set +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.kt new file mode 100644 index 00000000000..d97164f3fd2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open var foo: Int = 2 + internal set +} +expect class Foo : Base { + override var foo: Int + internal set +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + actual override var foo: Int = 2 + public set +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt new file mode 100644 index 00000000000..155e92bfebf --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt @@ -0,0 +1,17 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open var foo: Int = 2 + protected set +} +expect class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Foo : Base() { + override var foo: Int = 2 + public set +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index d1e210dc6ff..8419365b01a 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -23734,6 +23734,36 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt"); } + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal.kt") + public void testWiderVisibility_expectIsEffectivelyFinal() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt") + public void testWiderVisibility_expectIsEffectivelyFinal_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_fakeOverride.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt") + public void testWiderVisibility_expectIsEffectivelyFinal_oldLanguageVersion() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectIsEffectivelyFinal_oldLanguageVersion.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectSetterIsEffectivelyFinal.kt") + public void testWiderVisibility_expectSetterIsEffectivelyFinal() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal.kt"); + } + + @Test + @TestMetadata("widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt") + public void testWiderVisibility_expectSetterIsEffectivelyFinal_fakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibility_expectSetterIsEffectivelyFinal_fakeOverride.kt"); + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 4ee8363e51e..e1639e06394 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -303,6 +303,7 @@ enum class LanguageFeature( KeepNullabilityWhenApproximatingLocalType(KOTLIN_2_0, kind = BUG_FIX), // KT-53982 ProhibitAccessToInvisibleSetterFromDerivedClass(KOTLIN_2_0, kind = BUG_FIX), // KT-56662 ProhibitOpenValDeferredInitialization(KOTLIN_2_0, kind = BUG_FIX), // KT-57553 + SupportEffectivelyFinalInExpectActualVisibilityCheck(KOTLIN_2_0, kind = BUG_FIX), // KT-61955 ProhibitMissedMustBeInitializedWhenThereIsNoPrimaryConstructor(KOTLIN_2_0, kind = BUG_FIX), // KT-58472 MangleCallsToJavaMethodsWithValueClasses(KOTLIN_2_0, kind = OTHER), // KT-55945 ForbidInferringTypeVariablesIntoEmptyIntersection(KOTLIN_2_0, kind = BUG_FIX), // KT-51221