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 e4b476d0800..279707dc95c 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 @@ -307,6 +307,382 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt"); } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker") + @TestDataPath("$PROJECT_ROOT") + public class ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker { + @Test + @TestMetadata("actualTypealias.kt") + public void testActualTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.kt"); + } + + @Test + @TestMetadata("actualizeFakeOverridePropertyToJavaMethod.kt") + public void testActualizeFakeOverridePropertyToJavaMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeFakeOverridePropertyToJavaMethod.kt"); + } + + @Test + @TestMetadata("actualizePrimaryConstructorWithSecondaryConstructor.kt") + public void testActualizePrimaryConstructorWithSecondaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizePrimaryConstructorWithSecondaryConstructor.kt"); + } + + @Test + @TestMetadata("actualizeSecondaryConstructorWithPrimaryConstructor.kt") + public void testActualizeSecondaryConstructorWithPrimaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeSecondaryConstructorWithPrimaryConstructor.kt"); + } + + @Test + public void testAllFilesPresentInActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("allowDifferentMembersInActual_class.kt") + public void testAllowDifferentMembersInActual_class() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_class.kt"); + } + + @Test + @TestMetadata("allowDifferentMembersInActual_typealias.kt") + public void testAllowDifferentMembersInActual_typealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_typealias.kt"); + } + + @Test + @TestMetadata("changeClassTypeParameterNames.kt") + public void testChangeClassTypeParameterNames() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeClassTypeParameterNames.kt"); + } + + @Test + @TestMetadata("changeFunctionTypeParameterNamesInOverride.kt") + public void testChangeFunctionTypeParameterNamesInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.kt"); + } + + @Test + @TestMetadata("changeLateinitInOverride.kt") + public void testChangeLateinitInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.kt"); + } + + @Test + @TestMetadata("changeModalityInOverride.kt") + public void testChangeModalityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.kt"); + } + + @Test + @TestMetadata("changeModalityOfSubstitutedFakeOverride.kt") + public void testChangeModalityOfSubstitutedFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.kt"); + } + + @Test + @TestMetadata("changeModalityOfToStringInOverride.kt") + public void testChangeModalityOfToStringInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.kt"); + } + + @Test + @TestMetadata("changeParameterNameInOverride.kt") + public void testChangeParameterNameInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.kt"); + } + + @Test + @TestMetadata("changeSetterVisibilityInOverride.kt") + public void testChangeSetterVisibilityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.kt"); + } + + @Test + @TestMetadata("changeVisibilityInOverride.kt") + public void testChangeVisibilityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.kt"); + } + + @Test + @TestMetadata("covariantFunctionOverride.kt") + public void testCovariantFunctionOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.kt"); + } + + @Test + @TestMetadata("covariantOverrideGenericUpperBound.kt") + public void testCovariantOverrideGenericUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.kt"); + } + + @Test + @TestMetadata("covariantOverrideGenerics.kt") + public void testCovariantOverrideGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.kt"); + } + + @Test + @TestMetadata("covariantPropertyOverride.kt") + public void testCovariantPropertyOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.kt"); + } + + @Test + @TestMetadata("fakeOverrideChangedToRealOverride.kt") + public void testFakeOverrideChangedToRealOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/fakeOverrideChangedToRealOverride.kt"); + } + + @Test + @TestMetadata("finalClassIsActualizedByOpenClass.kt") + public void testFinalClassIsActualizedByOpenClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalClassIsActualizedByOpenClass.kt"); + } + + @Test + @TestMetadata("finalMethodIsActualizedByOpenMethod.kt") + public void testFinalMethodIsActualizedByOpenMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.kt"); + } + + @Test + @TestMetadata("flexibleTypesMatching.kt") + public void testFlexibleTypesMatching() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.kt"); + } + + @Test + @TestMetadata("injectClass.kt") + public void testInjectClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectClass.kt"); + } + + @Test + @TestMetadata("injectContextReceiverOverload.kt") + public void testInjectContextReceiverOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.kt"); + } + + @Test + @TestMetadata("injectEmptySuperClass.kt") + public void testInjectEmptySuperClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.kt"); + } + + @Test + @TestMetadata("injectExtensionReceiverOverload.kt") + public void testInjectExtensionReceiverOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.kt"); + } + + @Test + @TestMetadata("injectGenericUpperBoundOverload.kt") + public void testInjectGenericUpperBoundOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.kt"); + } + + @Test + @TestMetadata("injectMethod_internalMethod.kt") + public void testInjectMethod_internalMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_privateMethod.kt") + public void testInjectMethod_privateMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_privateMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_protectedMethod.kt") + public void testInjectMethod_protectedMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_publicMethod.kt") + public void testInjectMethod_publicMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_publicMethodInJava.kt") + public void testInjectMethod_publicMethodInJava() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.kt"); + } + + @Test + @TestMetadata("injectParameterOverload.kt") + public void testInjectParameterOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.kt"); + } + + @Test + @TestMetadata("injectParameterOverloadWithGenerics.kt") + public void testInjectParameterOverloadWithGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.kt"); + } + + @Test + @TestMetadata("injectPrimaryConstructor.kt") + public void testInjectPrimaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrimaryConstructor.kt"); + } + + @Test + @TestMetadata("injectPrivateProperty.kt") + public void testInjectPrivateProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrivateProperty.kt"); + } + + @Test + @TestMetadata("injectProperty.kt") + public void testInjectProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.kt"); + } + + @Test + @TestMetadata("injectPropertyWithTheSameSignatureAsExistingFunction.kt") + public void testInjectPropertyWithTheSameSignatureAsExistingFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.kt"); + } + + @Test + @TestMetadata("injectPublicFakeOverrideMethod.kt") + public void testInjectPublicFakeOverrideMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.kt"); + } + + @Test + @TestMetadata("injectSecondaryConstructor.kt") + public void testInjectSecondaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSecondaryConstructor.kt"); + } + + @Test + @TestMetadata("injectSupertype_SupertypeIsExpectActualPair.kt") + public void testInjectSupertype_SupertypeIsExpectActualPair() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.kt"); + } + + @Test + @TestMetadata("injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt") + public void testInjectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt"); + } + + @Test + @TestMetadata("injectVarargParameterOverload.kt") + public void testInjectVarargParameterOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.kt"); + } + + @Test + @TestMetadata("nestedExpectOpenClass.kt") + public void testNestedExpectOpenClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.kt"); + } + + @Test + @TestMetadata("propertyKindOverride.kt") + public void testPropertyKindOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.kt"); + } + + @Test + @TestMetadata("severalMismatches.kt") + public void testSeveralMismatches() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.kt"); + } + + @Test + @TestMetadata("substitutedFakeOverrideChangedToRealOverride.kt") + public void testSubstitutedFakeOverrideChangedToRealOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/substitutedFakeOverrideChangedToRealOverride.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloActualTypealias.kt") + public void testSuperTypesAreTheSameModuloActualTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloActualTypealias.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloTypealias1.kt") + public void testSuperTypesAreTheSameModuloTypealias1() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias1.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloTypealias2.kt") + public void testSuperTypesAreTheSameModuloTypealias2() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias2.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt") + public void testSupertypeIsExpectActual_covariantOverrideOfInjectedFromSuper() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectMethod.kt") + public void testSupertypeIsExpectActual_injectMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectSupertype.kt") + public void testSupertypeIsExpectActual_injectSupertype() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_simpleOverride.kt") + public void testSupertypeIsExpectActual_simpleOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt") + public void testSupertypeIsExpectActual_supertypeIsActualTypealias_injectMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/annotationMatching") @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 5b8f3ab9f7f..34699a59442 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 @@ -307,6 +307,382 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt"); } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker") + @TestDataPath("$PROJECT_ROOT") + public class ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker { + @Test + @TestMetadata("actualTypealias.kt") + public void testActualTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.kt"); + } + + @Test + @TestMetadata("actualizeFakeOverridePropertyToJavaMethod.kt") + public void testActualizeFakeOverridePropertyToJavaMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeFakeOverridePropertyToJavaMethod.kt"); + } + + @Test + @TestMetadata("actualizePrimaryConstructorWithSecondaryConstructor.kt") + public void testActualizePrimaryConstructorWithSecondaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizePrimaryConstructorWithSecondaryConstructor.kt"); + } + + @Test + @TestMetadata("actualizeSecondaryConstructorWithPrimaryConstructor.kt") + public void testActualizeSecondaryConstructorWithPrimaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeSecondaryConstructorWithPrimaryConstructor.kt"); + } + + @Test + public void testAllFilesPresentInActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("allowDifferentMembersInActual_class.kt") + public void testAllowDifferentMembersInActual_class() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_class.kt"); + } + + @Test + @TestMetadata("allowDifferentMembersInActual_typealias.kt") + public void testAllowDifferentMembersInActual_typealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_typealias.kt"); + } + + @Test + @TestMetadata("changeClassTypeParameterNames.kt") + public void testChangeClassTypeParameterNames() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeClassTypeParameterNames.kt"); + } + + @Test + @TestMetadata("changeFunctionTypeParameterNamesInOverride.kt") + public void testChangeFunctionTypeParameterNamesInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.kt"); + } + + @Test + @TestMetadata("changeLateinitInOverride.kt") + public void testChangeLateinitInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.kt"); + } + + @Test + @TestMetadata("changeModalityInOverride.kt") + public void testChangeModalityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.kt"); + } + + @Test + @TestMetadata("changeModalityOfSubstitutedFakeOverride.kt") + public void testChangeModalityOfSubstitutedFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.kt"); + } + + @Test + @TestMetadata("changeModalityOfToStringInOverride.kt") + public void testChangeModalityOfToStringInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.kt"); + } + + @Test + @TestMetadata("changeParameterNameInOverride.kt") + public void testChangeParameterNameInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.kt"); + } + + @Test + @TestMetadata("changeSetterVisibilityInOverride.kt") + public void testChangeSetterVisibilityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.kt"); + } + + @Test + @TestMetadata("changeVisibilityInOverride.kt") + public void testChangeVisibilityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.kt"); + } + + @Test + @TestMetadata("covariantFunctionOverride.kt") + public void testCovariantFunctionOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.kt"); + } + + @Test + @TestMetadata("covariantOverrideGenericUpperBound.kt") + public void testCovariantOverrideGenericUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.kt"); + } + + @Test + @TestMetadata("covariantOverrideGenerics.kt") + public void testCovariantOverrideGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.kt"); + } + + @Test + @TestMetadata("covariantPropertyOverride.kt") + public void testCovariantPropertyOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.kt"); + } + + @Test + @TestMetadata("fakeOverrideChangedToRealOverride.kt") + public void testFakeOverrideChangedToRealOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/fakeOverrideChangedToRealOverride.kt"); + } + + @Test + @TestMetadata("finalClassIsActualizedByOpenClass.kt") + public void testFinalClassIsActualizedByOpenClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalClassIsActualizedByOpenClass.kt"); + } + + @Test + @TestMetadata("finalMethodIsActualizedByOpenMethod.kt") + public void testFinalMethodIsActualizedByOpenMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.kt"); + } + + @Test + @TestMetadata("flexibleTypesMatching.kt") + public void testFlexibleTypesMatching() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.kt"); + } + + @Test + @TestMetadata("injectClass.kt") + public void testInjectClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectClass.kt"); + } + + @Test + @TestMetadata("injectContextReceiverOverload.kt") + public void testInjectContextReceiverOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.kt"); + } + + @Test + @TestMetadata("injectEmptySuperClass.kt") + public void testInjectEmptySuperClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.kt"); + } + + @Test + @TestMetadata("injectExtensionReceiverOverload.kt") + public void testInjectExtensionReceiverOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.kt"); + } + + @Test + @TestMetadata("injectGenericUpperBoundOverload.kt") + public void testInjectGenericUpperBoundOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.kt"); + } + + @Test + @TestMetadata("injectMethod_internalMethod.kt") + public void testInjectMethod_internalMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_privateMethod.kt") + public void testInjectMethod_privateMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_privateMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_protectedMethod.kt") + public void testInjectMethod_protectedMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_publicMethod.kt") + public void testInjectMethod_publicMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_publicMethodInJava.kt") + public void testInjectMethod_publicMethodInJava() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.kt"); + } + + @Test + @TestMetadata("injectParameterOverload.kt") + public void testInjectParameterOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.kt"); + } + + @Test + @TestMetadata("injectParameterOverloadWithGenerics.kt") + public void testInjectParameterOverloadWithGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.kt"); + } + + @Test + @TestMetadata("injectPrimaryConstructor.kt") + public void testInjectPrimaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrimaryConstructor.kt"); + } + + @Test + @TestMetadata("injectPrivateProperty.kt") + public void testInjectPrivateProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrivateProperty.kt"); + } + + @Test + @TestMetadata("injectProperty.kt") + public void testInjectProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.kt"); + } + + @Test + @TestMetadata("injectPropertyWithTheSameSignatureAsExistingFunction.kt") + public void testInjectPropertyWithTheSameSignatureAsExistingFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.kt"); + } + + @Test + @TestMetadata("injectPublicFakeOverrideMethod.kt") + public void testInjectPublicFakeOverrideMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.kt"); + } + + @Test + @TestMetadata("injectSecondaryConstructor.kt") + public void testInjectSecondaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSecondaryConstructor.kt"); + } + + @Test + @TestMetadata("injectSupertype_SupertypeIsExpectActualPair.kt") + public void testInjectSupertype_SupertypeIsExpectActualPair() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.kt"); + } + + @Test + @TestMetadata("injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt") + public void testInjectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt"); + } + + @Test + @TestMetadata("injectVarargParameterOverload.kt") + public void testInjectVarargParameterOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.kt"); + } + + @Test + @TestMetadata("nestedExpectOpenClass.kt") + public void testNestedExpectOpenClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.kt"); + } + + @Test + @TestMetadata("propertyKindOverride.kt") + public void testPropertyKindOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.kt"); + } + + @Test + @TestMetadata("severalMismatches.kt") + public void testSeveralMismatches() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.kt"); + } + + @Test + @TestMetadata("substitutedFakeOverrideChangedToRealOverride.kt") + public void testSubstitutedFakeOverrideChangedToRealOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/substitutedFakeOverrideChangedToRealOverride.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloActualTypealias.kt") + public void testSuperTypesAreTheSameModuloActualTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloActualTypealias.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloTypealias1.kt") + public void testSuperTypesAreTheSameModuloTypealias1() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias1.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloTypealias2.kt") + public void testSuperTypesAreTheSameModuloTypealias2() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias2.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt") + public void testSupertypeIsExpectActual_covariantOverrideOfInjectedFromSuper() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectMethod.kt") + public void testSupertypeIsExpectActual_injectMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectSupertype.kt") + public void testSupertypeIsExpectActual_injectSupertype() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_simpleOverride.kt") + public void testSupertypeIsExpectActual_simpleOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt") + public void testSupertypeIsExpectActual_supertypeIsActualTypealias_injectMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/annotationMatching") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 1bafa971057..80ece07e405 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.util.BuilderLambdaLabelingInfo; import org.jetbrains.kotlin.resolve.deprecation.DescriptorBasedDeprecationInfo; import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType; import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible; +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMemberDiff; import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData; import org.jetbrains.kotlin.types.KotlinType; @@ -839,6 +840,32 @@ public interface Errors { DiagnosticFactory1 EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE = DiagnosticFactory1.create(WARNING, DECLARATION_NAME); + DiagnosticFactory3>, ClassDescriptor> + ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_MEMBERS_AS_NON_FINAL_EXPECT_CLASSIFIER = + DiagnosticFactory3.create(ERROR, DECLARATION_NAME); + DiagnosticFactory1> + NON_ACTUAL_MEMBER_DECLARED_IN_EXPECT_NON_FINAL_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, DECLARATION_NAME); + DiagnosticFactory1> + RETURN_TYPE_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, DECLARATION_RETURN_TYPE); + DiagnosticFactory1> + MODALITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, MODALITY_MODIFIER); + DiagnosticFactory1> + VISIBILITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, VISIBILITY_MODIFIER); + DiagnosticFactory1> + SETTER_VISIBILITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, VISIBILITY_MODIFIER); + DiagnosticFactory1> + PARAMETER_NAME_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, DECLARATION_NAME); + DiagnosticFactory1> + PROPERTY_KIND_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, VAL_OR_VAR_NODE); + DiagnosticFactory1> + LATEINIT_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, LATEINIT_MODIFIER); + DiagnosticFactory1> + TYPE_PARAMETER_NAMES_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION = DiagnosticFactory1.create(ERROR, TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE); + + DiagnosticFactory3, ClassDescriptor> + ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_SUPERTYPES_AS_NON_FINAL_EXPECT_CLASSIFIER = + DiagnosticFactory3.create(ERROR, DECLARATION_NAME); + DiagnosticFactory0 OPTIONAL_EXPECTATION_NOT_ON_EXPECTED = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index a3a07b644e6..96941d9ed63 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -395,6 +395,42 @@ public class DefaultErrorMessages { "{0}: expect and corresponding actual are declared in the same module, which will be prohibited in Kotlin 2.0. See https://youtrack.jetbrains.com/issue/KT-55177", CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM); + MAP.put(ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_MEMBERS_AS_NON_FINAL_EXPECT_CLASSIFIER, + "{0}: actual class and its non-final expect class must declare exactly the same non-private members. " + + "The following non-private members in actual class are mismatched:{1}\n" + + "This error happens because the expect class ''{2}'' is non-final. " + + "Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", + CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, + ExpectActualScopeDiffsRenderer.TEXT, + NAME); + MAP.put(NON_ACTUAL_MEMBER_DECLARED_IN_EXPECT_NON_FINAL_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(RETURN_TYPE_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(MODALITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(VISIBILITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(PARAMETER_NAME_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(PROPERTY_KIND_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(LATEINIT_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(SETTER_VISIBILITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + MAP.put(TYPE_PARAMETER_NAMES_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION, + "{0}. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", ExpectActualScopeDiffRenderer.INSTANCE); + + MAP.put(ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_SUPERTYPES_AS_NON_FINAL_EXPECT_CLASSIFIER, + "{0}: actual class and its non-final expect class must declare exactly the same supertypes. " + + "Actual class declares the following supertypes that are not presented in expect class: {1}. " + + "This error happens because the expect class ''{2}'' is non-final. " + + "Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details", + CAPITALIZED_DECLARATION_NAME_WITH_KIND_AND_PLATFORM, + new ListRenderer<>(TO_STRING, (elem) -> "'" + elem + "'"), + NAME); + MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class"); MAP.put(OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, "Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry"); MAP.put(OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE, "Declaration annotated with '@OptionalExpectation' can only be used in common module sources"); @@ -1287,7 +1323,7 @@ public class DefaultErrorMessages { } @SuppressWarnings("unchecked") - public static DiagnosticParameterRenderer, Collection>>>> adaptGenerics2(DiagnosticParameterRenderer, ? extends Collection>>>> renderer) { + public static DiagnosticParameterRenderer, Collection>>>> adaptGenerics2(DiagnosticParameterRenderer, ? extends Collection>>>> renderer) { return (obj, renderingContext) -> renderer.render((List)obj, renderingContext); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/PlatformIncompatibilityDiagnosticRenderer.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/PlatformIncompatibilityDiagnosticRenderer.kt index 8fe76f3f720..f841b870468 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/PlatformIncompatibilityDiagnosticRenderer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/PlatformIncompatibilityDiagnosticRenderer.kt @@ -16,9 +16,13 @@ package org.jetbrains.kotlin.diagnostics.rendering +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMemberDiff +import java.text.MessageFormat class PlatformIncompatibilityDiagnosticRenderer( private val mode: MultiplatformDiagnosticRenderingMode @@ -62,6 +66,49 @@ class IncompatibleExpectedActualClassScopesRenderer( } } +class ExpectActualScopeDiffsRenderer( + private val mode: MultiplatformDiagnosticRenderingMode, +) : DiagnosticParameterRenderer>> { + override fun render( + obj: Set>, + renderingContext: RenderingContext, + ): String { + check(obj.isNotEmpty()) + return buildString { + mode.renderList(this, obj.toList().map { diff -> + { + appendLine() + appendLine(ExpectActualScopeDiffRenderer.render(diff, renderingContext)) + } + }) + } + } + + companion object { + @JvmField + val TEXT = ExpectActualScopeDiffsRenderer(MultiplatformDiagnosticRenderingMode()) + } +} + +object ExpectActualScopeDiffRenderer : DiagnosticParameterRenderer> { + override fun render( + obj: ExpectActualMemberDiff, + renderingContext: RenderingContext, + ): String = MessageFormat.format( + obj.kind.rawMessage, + Renderers.DECLARATION_NAME_WITH_KIND.render(obj.actualMember, renderingContext), + Renderers.NAME.render(obj.expectClass) + ) +} + +class ListRenderer( + private val elementRenderer: DiagnosticParameterRenderer, + private val elemProcessor: (String) -> String = { it }, +) : DiagnosticParameterRenderer> { + override fun render(obj: List, renderingContext: RenderingContext): String = + obj.joinToString { elemProcessor(elementRenderer.render(it, renderingContext)) } +} + open class MultiplatformDiagnosticRenderingMode { open fun newLine(sb: StringBuilder) { sb.appendLine() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt index db44360537f..cab9aa77e2e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.types.DynamicTypesSettings private val DEFAULT_DECLARATION_CHECKERS = listOf( ExpectActualInTheSameModuleChecker, + ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker, DataClassDeclarationChecker(), ConstModifierChecker, UnderscoreChecker, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt new file mode 100644 index 00000000000..ff1aaada994 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker.kt @@ -0,0 +1,360 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.checkers + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.descriptorUtil.* +import org.jetbrains.kotlin.resolve.multiplatform.* +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.resolve.source.KotlinSourceElement +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker +import java.util.* +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +object ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker : DeclarationChecker { + override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { + val (actual, expect) = matchActualWithNonFinalExpect(declaration, descriptor, context) ?: return + + // The explicit casts won't be necessary when we start compiling kotlin with K2. K1 doesn't build CFG properly + declaration as KtClassLikeDeclaration + descriptor as ClassifierDescriptorWithTypeParameters + + checkSupertypes(actual, expect, context, declaration, descriptor) + checkExpectActualScopeDiff(expect, actual, context, declaration, descriptor) + } +} + +private fun checkSupertypes( + actual: ClassDescriptor, + expect: ClassDescriptor, + context: DeclarationCheckerContext, + declaration: KtClassLikeDeclaration, + descriptor: ClassifierDescriptorWithTypeParameters, +) { + val addedSupertypes = (actual.getSuperInterfaces() + listOfNotNull(actual.getSuperClassNotAny())).map(ClassDescriptor::fqNameSafe) - + (expect.getSuperInterfaces() + listOfNotNull(expect.getSuperClassNotAny())).map(ClassDescriptor::fqNameSafe).toSet() + + if (addedSupertypes.isNotEmpty()) { + context.trace.report( + Errors.ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_SUPERTYPES_AS_NON_FINAL_EXPECT_CLASSIFIER.on( + declaration, + descriptor, + addedSupertypes.map(FqName::shortName), + expect, + ) + ) + } +} + +private fun checkExpectActualScopeDiff( + expect: ClassDescriptor, + actual: ClassDescriptor, + context: DeclarationCheckerContext, + declaration: KtClassLikeDeclaration, + descriptor: ClassifierDescriptorWithTypeParameters, +) { + val scopeDiff = calculateExpectActualScopeDiff(expect, actual) + if (scopeDiff.isNotEmpty()) { + context.trace.report( + Errors.ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_MEMBERS_AS_NON_FINAL_EXPECT_CLASSIFIER.on( + declaration, + descriptor, + scopeDiff, + scopeDiff.first().expectClass, // All expect classes in scopeDiff are the same + ) + ) + } + if (descriptor !is TypeAliasDescriptor) { + for (diff in scopeDiff) { + // If it can't be reported, it's not a big deal, because this error is already + // reported on the 'actual class' itself (see code above) + context.trace.reportIfPossible(diff) + } + } +} + +private val allowDifferentMembersInActualFqn = FqName("kotlin.AllowDifferentMembersInActual") + +@OptIn(ExperimentalContracts::class) +internal fun matchActualWithNonFinalExpect( + declaration: KtDeclaration, + descriptor: DeclarationDescriptor, + context: DeclarationCheckerContext, +): Pair? { + contract { + returnsNotNull() implies (declaration is KtClassLikeDeclaration) + returnsNotNull() implies (descriptor is ClassifierDescriptorWithTypeParameters) + } + if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) return null + if (declaration !is KtTypeAlias && declaration !is KtClassOrObject) return null + if (descriptor !is TypeAliasDescriptor && descriptor !is ClassDescriptor) return null + + // Common supertype of KtTypeAlias and KtClassOrObject is KtClassLikeDeclaration. + // Common supertype of TypeAliasDescriptor and ClassDescriptor is ClassifierDescriptorWithTypeParameters. + // The explicit casts won't be necessary when we start compiling kotlin with K2. + declaration as KtClassLikeDeclaration + descriptor as ClassifierDescriptorWithTypeParameters + + if (!descriptor.isActual) return null + + with(OptInUsageChecker) { + if (declaration.isDeclarationAnnotatedWith(allowDifferentMembersInActualFqn, context.trace.bindingContext)) return null + } + + val actual = when (descriptor) { + is ClassDescriptor -> descriptor + is TypeAliasDescriptor -> descriptor.classDescriptor + else -> error("ClassifierDescriptorWithTypeParameters has only two inheritors") + } ?: return null + // If actual is final then expect is final as well (otherwise another checker will report a diagnostic). + // There is no need to waste time searching for the appropriate expect and checking its modality. This `if` is an optimization + if (actual.modality == Modality.FINAL) return null + + val expect = ExpectedActualResolver.findExpectedForActual(descriptor) + ?.get(ExpectActualCompatibility.Compatible) + ?.singleOrNull() as? ClassDescriptor // if actual has more than one expects then it will be reported by another checker + ?: return null + + if (expect.modality == Modality.FINAL) return null + return actual to expect +} + +private fun calculateExpectActualScopeDiff( + expect: ClassDescriptor, + actual: ClassDescriptor, +): Set> { + val matchingContext = ClassicExpectActualMatchingContext(actual.module) + val classTypeSubstitutor = matchingContext.createExpectActualTypeParameterSubstitutor( + expect.declaredTypeParameters, + actual.declaredTypeParameters, + parentSubstitutor = null + ) + + val expectClassCallables = expect.unsubstitutedMemberScope + .extractNonPrivateCallables(classTypeSubstitutor, ExpectActual.EXPECT, matchingContext) + val actualClassCallables = actual.unsubstitutedMemberScope + .extractNonPrivateCallables(classTypeSubstitutor, ExpectActual.ACTUAL, matchingContext) + .filter { it.descriptor.kind.isReal } // Filter out fake-overrides from actual because we compare list of supertypes separately anyway + + val nameAndKindToExpectCallable = expectClassCallables.groupBy { it.name to it.kind } + + return (actualClassCallables - expectClassCallables).asSequence() + .flatMap { unmatchedActualCallable -> + when (val expectCallablesWithTheSameNameAndKind = + nameAndKindToExpectCallable[unmatchedActualCallable.name to unmatchedActualCallable.kind]) { + null -> listOf(ExpectActualMemberDiff.Kind.NonPrivateCallableAdded) + else -> expectCallablesWithTheSameNameAndKind.map { + calculateExpectActualMemberDiffKind( + expect = it, + actual = unmatchedActualCallable, + checkParameterNames = unmatchedActualCallable.descriptor.hasStableParameterNames() + ) + } + }.filterNotNull().map { kind -> ExpectActualMemberDiff(kind, unmatchedActualCallable.descriptor, expect) } + } + .toSet() +} + +private fun MemberScope.extractNonPrivateCallables( + classTypeSubstitutor: TypeSubstitutorMarker, + expectActual: ExpectActual, + matchingContext: ClassicExpectActualMatchingContext, +): Set { + val functions = + getFunctionNames().asSequence().flatMap { getContributedFunctions(it, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS) } + val properties = + getVariableNames().asSequence().flatMap { getContributedVariables(it, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS) } + return (functions + properties).filter { !Visibilities.isPrivate(it.visibility.delegate) } + .map { descriptor -> Callable(descriptor, expectActual, classTypeSubstitutor, matchingContext) } + .toSet() +} + +private data class Parameter(val name: Name, val type: KotlinType) +private enum class Kind { FUNCTION, PROPERTY } +private enum class ExpectActual { EXPECT, ACTUAL } +private data class TypeParameter(val name: Name, val upperBounds: List) +private class Callable( + val descriptor: CallableMemberDescriptor, + val expectActual: ExpectActual, + val classTypeSubstitutor: TypeSubstitutorMarker, + val matchingContext: ClassicExpectActualMatchingContext, +) { + val name: Name = descriptor.name + val kind: Kind = when (descriptor) { + is PropertyDescriptor -> Kind.PROPERTY + is FunctionDescriptor -> Kind.FUNCTION + else -> error("Unknown kind $descriptor") + } + val isVarProperty: Boolean = descriptor is PropertyDescriptor && descriptor.isVar + val isLateinitProperty: Boolean = descriptor is PropertyDescriptor && descriptor.isLateInit + val modality: Modality = descriptor.modality + val visibility: Visibility = descriptor.visibility.delegate + val setterVisibility: Visibility? = (descriptor as? PropertyDescriptor)?.setter?.visibility?.delegate + val parameters: List = descriptor.valueParameters.map { Parameter(it.name, it.type) } + val returnType: KotlinType = descriptor.returnType ?: error("Can't get return type") + val extensionReceiverType: KotlinType? = descriptor.extensionReceiverParameter?.type + val typeParameters: List = descriptor.typeParameters.map { TypeParameter(it.name, it.upperBounds) } + val contextReceiverTypes: List = descriptor.contextReceiverParameters.map(ValueDescriptor::getType) + + override fun equals(other: Any?): Boolean { + if (other !is Callable) return false + check(classTypeSubstitutor === other.classTypeSubstitutor) + check(matchingContext === other.matchingContext) + return if (expectActual == other.expectActual) { + name == other.name && + kind == other.kind && + isVarProperty == other.isVarProperty && + isLateinitProperty == other.isLateinitProperty && + modality == other.modality && + visibility == other.visibility && + setterVisibility == other.setterVisibility && + parameters == other.parameters && + returnType == other.returnType && + extensionReceiverType == other.extensionReceiverType && + typeParameters == other.typeParameters && + contextReceiverTypes == other.contextReceiverTypes + } else { + val (expect, actual) = if (expectActual == ExpectActual.EXPECT) this to other else other to this + calculateExpectActualMemberDiffKind(expect, actual) == null + } + } + + override fun hashCode(): Int = // Don't hash the types because type comparison is complicated + Objects.hash( + name, + kind, + isVarProperty, + isLateinitProperty, + modality, + visibility, + setterVisibility, + parameters.map(Parameter::name), + extensionReceiverType != null, + typeParameters.map(TypeParameter::name), + contextReceiverTypes.size, + ) +} + +private val CallableMemberDescriptor.psiIfReal: KtCallableDeclaration? + get() = takeIf { it.kind.isReal }?.source?.let { it as? KotlinSourceElement }?.psi as? KtCallableDeclaration + +private fun ClassicExpectActualMatchingContext.areCompatibleWithSubstitution( + expect: KotlinType?, + actual: KotlinType?, + substitutor: TypeSubstitutorMarker, +): Boolean = areCompatibleExpectActualTypes(expect?.let { substitutor.safeSubstitute(it) }, actual) + +private fun ClassicExpectActualMatchingContext.areCompatibleListWithSubstitution( + expect: List, + actual: List, + substitutor: TypeSubstitutorMarker, +): Boolean = expect.size == actual.size && expect.asSequence().zip(actual.asSequence()) + .all { (a, b) -> areCompatibleWithSubstitution(a, b, substitutor) } + +private fun ClassicExpectActualMatchingContext.areCompatibleUpperBoundsWithSubstitution( + expect: List>, + actual: List>, + substitutor: TypeSubstitutorMarker, +): Boolean = expect.size == actual.size && expect.asSequence().zip(actual.asSequence()) + .all { (a, b) -> areCompatibleListWithSubstitution(a, b, substitutor) } + +private fun calculateExpectActualMemberDiffKind( + expect: Callable, + actual: Callable, + checkParameterNames: Boolean = true, +): ExpectActualMemberDiff.Kind? { + check(expect.expectActual == ExpectActual.EXPECT) + check(actual.expectActual == ExpectActual.ACTUAL) + check(expect.classTypeSubstitutor === actual.classTypeSubstitutor) + check(expect.matchingContext === actual.matchingContext) + val substitutor = actual.matchingContext.createExpectActualTypeParameterSubstitutor( + expect.descriptor.typeParameters, + actual.descriptor.typeParameters, + actual.classTypeSubstitutor + ) + with(actual.matchingContext) { + return when { + expect.name != actual.name || + expect.kind != actual.kind || + !areCompatibleListWithSubstitution( + expect.parameters.map(Parameter::type), + actual.parameters.map(Parameter::type), + substitutor + ) || + !areCompatibleUpperBoundsWithSubstitution( + expect.typeParameters.map(TypeParameter::upperBounds), + actual.typeParameters.map(TypeParameter::upperBounds), + substitutor + ) || + !areCompatibleWithSubstitution( + expect.extensionReceiverType, + actual.extensionReceiverType, + substitutor + ) || + !areCompatibleListWithSubstitution( + expect.contextReceiverTypes, + actual.contextReceiverTypes, + substitutor + ) -> + ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + + expect.isVarProperty != actual.isVarProperty -> ExpectActualMemberDiff.Kind.PropertyKindChangedInOverride + + expect.isLateinitProperty != actual.isLateinitProperty -> ExpectActualMemberDiff.Kind.LateinitChangedInOverride + + expect.modality != actual.modality -> ExpectActualMemberDiff.Kind.ModalityChangedInOverride + + expect.visibility != actual.visibility -> ExpectActualMemberDiff.Kind.VisibilityChangedInOverride + + expect.setterVisibility != actual.setterVisibility -> ExpectActualMemberDiff.Kind.SetterVisibilityChangedInOverride + + checkParameterNames && expect.parameters.map(Parameter::name) != actual.parameters.map(Parameter::name) -> + ExpectActualMemberDiff.Kind.ParameterNameChangedInOverride + + expect.typeParameters.map(TypeParameter::name) != actual.typeParameters.map(TypeParameter::name) -> + ExpectActualMemberDiff.Kind.TypeParameterNamesChangedInOverride + + !areCompatibleWithSubstitution(expect.returnType, actual.returnType, substitutor) -> + ExpectActualMemberDiff.Kind.ReturnTypeChangedInOverride + + else -> null + } + } +} + +private fun BindingTrace.reportIfPossible(diff: ExpectActualMemberDiff) { + val psi = diff.actualMember.psiIfReal ?: return + val diagnostic = when (diff.kind) { + ExpectActualMemberDiff.Kind.NonPrivateCallableAdded -> + Errors.NON_ACTUAL_MEMBER_DECLARED_IN_EXPECT_NON_FINAL_CLASSIFIER_ACTUALIZATION.on(psi, diff) + ExpectActualMemberDiff.Kind.ReturnTypeChangedInOverride -> + Errors.RETURN_TYPE_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on(psi, diff) + ExpectActualMemberDiff.Kind.ModalityChangedInOverride -> + Errors.MODALITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on(psi, diff) + ExpectActualMemberDiff.Kind.VisibilityChangedInOverride -> + Errors.VISIBILITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on(psi, diff) + ExpectActualMemberDiff.Kind.SetterVisibilityChangedInOverride -> + Errors.SETTER_VISIBILITY_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on((psi as? KtProperty)?.setter ?: return, diff) + ExpectActualMemberDiff.Kind.ParameterNameChangedInOverride -> + Errors.PARAMETER_NAME_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on(psi, diff) + ExpectActualMemberDiff.Kind.PropertyKindChangedInOverride -> + Errors.PROPERTY_KIND_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on(psi, diff) + ExpectActualMemberDiff.Kind.LateinitChangedInOverride -> + Errors.LATEINIT_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on(psi, diff) + ExpectActualMemberDiff.Kind.TypeParameterNamesChangedInOverride -> + Errors.TYPE_PARAMETER_NAMES_CHANGED_IN_NON_FINAL_EXPECT_CLASSIFIER_ACTUALIZATION.on(psi, diff) + } + report(diagnostic) +} diff --git a/compiler/testData/codegen/box/multiplatform/defaultArguments/bothInExpectAndActual2.kt b/compiler/testData/codegen/box/multiplatform/defaultArguments/bothInExpectAndActual2.kt index e47648ec2d3..a601dedb47a 100644 --- a/compiler/testData/codegen/box/multiplatform/defaultArguments/bothInExpectAndActual2.kt +++ b/compiler/testData/codegen/box/multiplatform/defaultArguments/bothInExpectAndActual2.kt @@ -1,4 +1,5 @@ // !LANGUAGE: +MultiPlatformProjects +// WITH_STDLIB // IGNORE_BACKEND: NATIVE // IGNORE_BACKEND_K2: ANY // FIR status: outdated code (expect and actual in the same module) @@ -20,6 +21,8 @@ actual interface I { actual fun test(source: String = "actual") } +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual actual interface J : I { override fun test(source: String) { if (source != "actual") throw AssertionError(source) diff --git a/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt b/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt index 396fd6a1dc2..b3b6678e19b 100644 --- a/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt +++ b/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt @@ -3,6 +3,7 @@ * Js backend is ignored because they use old test infrastructure which doesn't support HMPP */ +// WITH_STDLIB // !LANGUAGE: +MultiPlatformProjects // TARGET_BACKEND: JVM @@ -25,6 +26,8 @@ fun getB(): B = B() // MODULE: main()()(intermediate) // FILE: main.kt +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual actual open class A actual constructor() { fun bar(): String = "K" } diff --git a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt index 18178b4e179..0503b686df7 100644 --- a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt +++ b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt @@ -1,4 +1,5 @@ // IGNORE_BACKEND_K1: JS, JS_IR, JS_IR_ES6, NATIVE, WASM +// WITH_STDLIB // !LANGUAGE: +MultiPlatformProjects // MODULE: common @@ -17,12 +18,16 @@ class B : A() // MODULE: platform()()(common) // FILE: platform.kt +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual actual interface S1 { fun o(): S = "O" val p: Boolean get() = true } +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual actual interface S2 { fun k() = "K" } diff --git a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt index cc23696b53e..073ce871860 100644 --- a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt +++ b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt @@ -1,4 +1,5 @@ // IGNORE_BACKEND_K1: JS, JS_IR, JS_IR_ES6, NATIVE, WASM +// WITH_STDLIB // !LANGUAGE: +MultiPlatformProjects // MODULE: common @@ -17,6 +18,8 @@ class B : A() // MODULE: platform()()(common) // FILE: platform.kt +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual actual interface S1 { fun s1() = "O" } @@ -25,9 +28,13 @@ interface S20 { fun s2() = "K" } +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual actual interface S2 : S20 { } +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual actual interface S : S1, S2 { fun s3() = s1() + s2() } diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.fir.kt new file mode 100644 index 00000000000..9e5b081224b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.fir.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Foo = FooImpl + +open class FooImpl { + fun existingMethod() {} + val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.kt new file mode 100644 index 00000000000..f66c6f2e4de --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Foo = FooImpl + +open class FooImpl { + fun existingMethod() {} + val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeFakeOverridePropertyToJavaMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeFakeOverridePropertyToJavaMethod.kt new file mode 100644 index 00000000000..e4ee1ea1ec6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeFakeOverridePropertyToJavaMethod.kt @@ -0,0 +1,24 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +open class Base() { + open val foo: Int = 1 +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Foo = FooImpl + +// FILE: Foo.java + +public class FooImpl extends Base { + @Override + public int getFoo() { + return 1; + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizePrimaryConstructorWithSecondaryConstructor.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizePrimaryConstructorWithSecondaryConstructor.kt new file mode 100644 index 00000000000..0516851ef17 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizePrimaryConstructorWithSecondaryConstructor.kt @@ -0,0 +1,18 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo() { + fun existingFun() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingFun() {} + actual val existingParam: Int = 904 + + actual constructor() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeSecondaryConstructorWithPrimaryConstructor.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeSecondaryConstructorWithPrimaryConstructor.kt new file mode 100644 index 00000000000..b9469748cf6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeSecondaryConstructorWithPrimaryConstructor.kt @@ -0,0 +1,18 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingFun() + val existingParam: Int + + constructor() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo actual constructor() { + actual fun existingFun() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_class.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_class.kt new file mode 100644 index 00000000000..06d84f70a9f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_class.kt @@ -0,0 +1,21 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(kotlin.ExperimentalMultiplatform::class) +@kotlin.AllowDifferentMembersInActual +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_typealias.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_typealias.kt new file mode 100644 index 00000000000..18556e5b066 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_typealias.kt @@ -0,0 +1,23 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(kotlin.ExperimentalMultiplatform::class) +@kotlin.AllowDifferentMembersInActual +actual typealias Foo = FooImpl + +open class FooImpl { + fun existingMethod() {} + val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeClassTypeParameterNames.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeClassTypeParameterNames.kt new file mode 100644 index 00000000000..3b7adf91efa --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeClassTypeParameterNames.kt @@ -0,0 +1,25 @@ +// FIR_IDENTICAL +// LANGUAGE: +ContextReceivers +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun returnType(): T = null!! + open fun parameterType(t: T) {} + context(T) + open fun contextReceiverType() {} + open fun T.extensionReceiverType() {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun returnType(): R = null!! + override fun parameterType(t: R) {} + context(R) + override fun contextReceiverType() {} + override fun R.extensionReceiverType() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.fir.kt new file mode 100644 index 00000000000..c870d42ac67 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(t: R) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.kt new file mode 100644 index 00000000000..94eada8ea2b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(t: R) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.fir.kt new file mode 100644 index 00000000000..0941f5217b9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.fir.kt @@ -0,0 +1,20 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open var red1: String = "" + open lateinit var red2: String + open lateinit var green: String +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override lateinit var red1: String + override var red2: String = "" + override lateinit var green: String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.kt new file mode 100644 index 00000000000..a5dac19d71c --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.kt @@ -0,0 +1,20 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open var red1: String = "" + open lateinit var red2: String + open lateinit var green: String +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override lateinit var red1: String + override var red2: String = "" + override lateinit var green: String +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.fir.kt new file mode 100644 index 00000000000..e1c47a7c26b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo() {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + final override fun foo() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.kt new file mode 100644 index 00000000000..8acc5a8531d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo() {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + final override fun foo() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.fir.kt new file mode 100644 index 00000000000..a570ef59497 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + final override fun foo(t: String) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.kt new file mode 100644 index 00000000000..92c25f8d7bc --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + final override fun foo(t: String) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.fir.kt new file mode 100644 index 00000000000..8c974853ccc --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.fir.kt @@ -0,0 +1,11 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + final override fun toString() = "Foo" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.kt new file mode 100644 index 00000000000..5e9ff2de5af --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.kt @@ -0,0 +1,11 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + final override fun toString() = "Foo" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.fir.kt new file mode 100644 index 00000000000..07f18083e34 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.fir.kt @@ -0,0 +1,34 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(param: Int) {} +} + +expect open class Foo1 : Base +expect open class Foo2 : Base +expect open class Foo3 { + open fun foo(param: Int) +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo1 : Base() { + override fun foo(paramNameChanged: Int) {} +} + +actual typealias Foo2 = Foo2Java +actual typealias Foo3 = Foo3Java + +// FILE: Foo2Java.java + +public class Foo2Java extends Base { + @Override + public void foo(int paramNameChanged) {} +} + +// FILE: Foo3Java.java +public class Foo3Java { + public void foo(int paramNameChanged) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.kt new file mode 100644 index 00000000000..3ee1fbc160a --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.kt @@ -0,0 +1,34 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(param: Int) {} +} + +expect open class Foo1 : Base +expect open class Foo2 : Base +expect open class Foo3 { + open fun foo(param: Int) +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo1 : Base() { + override fun foo(paramNameChanged: Int) {} +} + +actual typealias Foo2 = Foo2Java +actual typealias Foo3 = Foo3Java + +// FILE: Foo2Java.java + +public class Foo2Java extends Base { + @Override + public void foo(int paramNameChanged) {} +} + +// FILE: Foo3Java.java +public class Foo3Java { + public void foo(int paramNameChanged) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.fir.kt new file mode 100644 index 00000000000..eecba805239 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open var foo: String = "" + protected set +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override var foo: String = "" + public set +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.kt new file mode 100644 index 00000000000..caab6bec78e --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open var foo: String = "" + protected set +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override var foo: String = "" + public set +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.fir.kt new file mode 100644 index 00000000000..53cba1cb298 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + protected open fun foo() {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + public override fun foo() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.kt new file mode 100644 index 00000000000..5fa8c07c287 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + protected open fun foo() {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + public override fun foo() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.fir.kt new file mode 100644 index 00000000000..1e17e6fb4f8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open val foo: String = "" + open fun foo(): Any = "" +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(): String = "" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.kt new file mode 100644 index 00000000000..5408738b119 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open val foo: String = "" + open fun foo(): Any = "" +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(): String = "" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.fir.kt new file mode 100644 index 00000000000..a8f85dec5ab --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.fir.kt @@ -0,0 +1,18 @@ +// MODULE: m1-common +// FILE: common.kt + +interface I + +open class Base { + open fun foo(): I = null!! +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(): T = null!! +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.kt new file mode 100644 index 00000000000..913263058fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.kt @@ -0,0 +1,18 @@ +// MODULE: m1-common +// FILE: common.kt + +interface I + +open class Base { + open fun foo(): I = null!! +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(): T = null!! +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.fir.kt new file mode 100644 index 00000000000..446a46e8afb --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.fir.kt @@ -0,0 +1,16 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(): R = null!! +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(): F = null!! +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.kt new file mode 100644 index 00000000000..1d315d00487 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.kt @@ -0,0 +1,16 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(): R = null!! +} + +expect open class Foo : Base { +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(): F = null!! +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.fir.kt new file mode 100644 index 00000000000..e292b3b1e6b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.fir.kt @@ -0,0 +1,16 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open val foo: Any = "" + open fun foo(): String = "" +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override val foo: String = "" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.kt new file mode 100644 index 00000000000..6ee7f652e83 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.kt @@ -0,0 +1,16 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open val foo: Any = "" + open fun foo(): String = "" +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override val foo: String = "" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/fakeOverrideChangedToRealOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/fakeOverrideChangedToRealOverride.kt new file mode 100644 index 00000000000..a073450b305 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/fakeOverrideChangedToRealOverride.kt @@ -0,0 +1,16 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo() {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalClassIsActualizedByOpenClass.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalClassIsActualizedByOpenClass.kt new file mode 100644 index 00000000000..e466cc1f2f6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalClassIsActualizedByOpenClass.kt @@ -0,0 +1,12 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect class Foo + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + fun injectedMethod() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.fir.kt new file mode 100644 index 00000000000..63b77ae33ab --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.fir.kt @@ -0,0 +1,16 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + // Hypothetically, it's more restricting than necessary. I can't see how actualizing final -> open can breaking anything. + // But technically, actual and expect scopes don't match + actual open fun foo() { + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.kt new file mode 100644 index 00000000000..284512114cf --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.kt @@ -0,0 +1,16 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + // Hypothetically, it's more restricting than necessary. I can't see how actualizing final -> open can breaking anything. + // But technically, actual and expect scopes don't match + actual open fun foo() { + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.fir.kt new file mode 100644 index 00000000000..882d8300fd3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.fir.kt @@ -0,0 +1,33 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + open fun foo(): MutableList +} + +expect open class Foo : Base { + +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Base = BaseJava + +actual open class Foo : Base() { + // K1 doesn't report a diagnostic here because when it compares scopes it sees flexible type + // K2 will likely report a diagnostic here + // I don't think we can fix this 'K1 green -> K2 red'. It must be a rare case anyway. + override fun foo(): List { + return super.foo() + } +} + +// FILE: BaseJava.java +import java.util.List; + +public class BaseJava { + public List foo() { + return null; + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.kt new file mode 100644 index 00000000000..2864d178ad6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.kt @@ -0,0 +1,33 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + open fun foo(): MutableList +} + +expect open class Foo : Base { + +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Base = BaseJava + +actual open class Foo : Base() { + // K1 doesn't report a diagnostic here because when it compares scopes it sees flexible type + // K2 will likely report a diagnostic here + // I don't think we can fix this 'K1 green -> K2 red'. It must be a rare case anyway. + override fun foo(): List { + return super.foo() + } +} + +// FILE: BaseJava.java +import java.util.List; + +public class BaseJava { + public List foo() { + return null; + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectClass.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectClass.kt new file mode 100644 index 00000000000..7f4ac88d10d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectClass.kt @@ -0,0 +1,24 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingFun() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingFun() {} + actual val existingParam: Int = 904 + + class InjectedClass + + // Injected classes can be considered as members (because they caputer `this`) => scopes are different + // => the diagnostic should be reported. + // + // But since `override inner class` isn't possible in Kotlin, red code here is unnecessary + inner class InjectedInnerClass +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.fir.kt new file mode 100644 index 00000000000..857f40455a9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.fir.kt @@ -0,0 +1,17 @@ +// LANGUAGE: +ContextReceivers +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo() {} + + context(Int) + fun foo() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.kt new file mode 100644 index 00000000000..3157c2d1172 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.kt @@ -0,0 +1,17 @@ +// LANGUAGE: +ContextReceivers +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo() {} + + context(Int) + fun foo() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.fir.kt new file mode 100644 index 00000000000..269e85b29d3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +open class InjectedEmptySuperClass() + +actual open class Foo : InjectedEmptySuperClass() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.kt new file mode 100644 index 00000000000..9ad92496da0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +open class InjectedEmptySuperClass() + +actual open class Foo : InjectedEmptySuperClass() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.fir.kt new file mode 100644 index 00000000000..10dbaedf6e8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo() {} + + fun Int.foo() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.kt new file mode 100644 index 00000000000..db2dfd84ed5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo() {} + + fun Int.foo() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.fir.kt new file mode 100644 index 00000000000..52d59aeab30 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + fun > foo(t: T) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.kt new file mode 100644 index 00000000000..ef84f475dcd --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + fun > foo(t: T) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.fir.kt new file mode 100644 index 00000000000..b3a8e7fac15 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + internal fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.kt new file mode 100644 index 00000000000..a9855217040 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + internal fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_privateMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_privateMethod.kt new file mode 100644 index 00000000000..348a1734ba6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_privateMethod.kt @@ -0,0 +1,18 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + private fun injected() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.fir.kt new file mode 100644 index 00000000000..3f2c5cabcb9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + protected fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.kt new file mode 100644 index 00000000000..32a3cc5839f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + protected fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.fir.kt new file mode 100644 index 00000000000..2c01e6b739e --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.kt new file mode 100644 index 00000000000..ae4137dd680 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.fir.kt new file mode 100644 index 00000000000..b5cdadf779c --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.fir.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Foo = FooImpl + +// FILE: Foo.java + +public class FooImpl { + public void existingMethod() {} + + public void injectedMethod() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.kt new file mode 100644 index 00000000000..1ebaedcc749 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Foo = FooImpl + +// FILE: Foo.java + +public class FooImpl { + public void existingMethod() {} + + public void injectedMethod() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.fir.kt new file mode 100644 index 00000000000..adb9cd60668 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo() {} + + fun foo(overloaded: Int) {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.kt new file mode 100644 index 00000000000..419ba7c4f8e --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo() {} + + fun foo(overloaded: Int) {} // accidential override can happen with this injected fun. That's why it's prohibited +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.fir.kt new file mode 100644 index 00000000000..552efaa250d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo() : Base() { + fun foo(t: T) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.kt new file mode 100644 index 00000000000..592a5f0fbd4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo() : Base() { + fun foo(t: T) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrimaryConstructor.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrimaryConstructor.kt new file mode 100644 index 00000000000..ba916da42dd --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrimaryConstructor.kt @@ -0,0 +1,16 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingFun() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo(injectedConstructor: Int) { + actual fun existingFun() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrivateProperty.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrivateProperty.kt new file mode 100644 index 00000000000..d3c034f5b93 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrivateProperty.kt @@ -0,0 +1,18 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingFun() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingFun() {} + actual val existingParam: Int = 904 + + private val injectedProperty = 1 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.fir.kt new file mode 100644 index 00000000000..e433fb14fa6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.fir.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingFun() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingFun() {} + actual val existingParam: Int = 904 + + val injectedProperty = 1 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.kt new file mode 100644 index 00000000000..1e3473f7147 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingFun() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingFun() {} + actual val existingParam: Int = 904 + + val injectedProperty = 1 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.fir.kt new file mode 100644 index 00000000000..e7a669192bf --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo(): Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo(): Int = 904 + + val foo: Int = 42 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.kt new file mode 100644 index 00000000000..c3e9132780a --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun foo(): Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun foo(): Int = 904 + + val foo: Int = 42 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.fir.kt new file mode 100644 index 00000000000..21ef0d8b3c5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.fir.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +open class Injector { + fun injectedMethod() {} +} + +actual open class Foo : Injector() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.kt new file mode 100644 index 00000000000..ab146159e6f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.kt @@ -0,0 +1,19 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +open class Injector { + fun injectedMethod() {} +} + +actual open class Foo : Injector() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSecondaryConstructor.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSecondaryConstructor.kt new file mode 100644 index 00000000000..c0ed757a1a0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSecondaryConstructor.kt @@ -0,0 +1,18 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + fun existingFun() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo { + actual fun existingFun() {} + actual val existingParam: Int = 904 + + constructor(injectedConstructor: Int) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.fir.kt new file mode 100644 index 00000000000..28aed272a33 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.fir.kt @@ -0,0 +1,24 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected() +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected() {} +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.kt new file mode 100644 index 00000000000..d604692a322 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.kt @@ -0,0 +1,24 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected() +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected() {} +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.fir.kt new file mode 100644 index 00000000000..f0d4ccecf04 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.fir.kt @@ -0,0 +1,26 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected() +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected() {} +} + +open class Transitive : Base() + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt new file mode 100644 index 00000000000..9838a3e51d2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt @@ -0,0 +1,26 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected() +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected() {} +} + +open class Transitive : Base() + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.fir.kt new file mode 100644 index 00000000000..2616b567569 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: String) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + open fun foo(vararg t: String) {} // injected +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.kt new file mode 100644 index 00000000000..45a6f3ed9a1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: String) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + open fun foo(vararg t: String) {} // injected +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.fir.kt new file mode 100644 index 00000000000..af1a182bc32 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.fir.kt @@ -0,0 +1,22 @@ +// MODULE: m1-common +// FILE: common.kt + +// Rules for expect actual matching are ad-hoc for nested classes. That's why this test exist +expect class Outer { + open class Foo { + fun existingMethod() + val existingParam: Int + } +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Outer { + actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.kt new file mode 100644 index 00000000000..c82fac3a1dd --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.kt @@ -0,0 +1,22 @@ +// MODULE: m1-common +// FILE: common.kt + +// Rules for expect actual matching are ad-hoc for nested classes. That's why this test exist +expect class Outer { + open class Foo { + fun existingMethod() + val existingParam: Int + } +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class Outer { + actual open class Foo { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + fun injectedMethod() {} // accidential override can happen with this injected fun. That's why it's prohibited + } +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.fir.kt new file mode 100644 index 00000000000..d5de594e915 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.fir.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open val foo: Int = 1 +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override var foo: Int = 1 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.kt new file mode 100644 index 00000000000..b882d86ac60 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open val foo: Int = 1 +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override var foo: Int = 1 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.fir.kt new file mode 100644 index 00000000000..b3424f1be20 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.fir.kt @@ -0,0 +1,29 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base() { + open fun overrideReturnType(): Any = "" + open fun overrideModality1(): Any = "" + open fun overrideModality2(): Any = "" + protected open fun overrideVisibility(): Any = "" +} + +expect open class Foo : Base { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + fun injectedMethod() {} + val injectedProperty: Int = 42 + override fun overrideReturnType(): String = "" + final override fun overrideModality1(): Any = "" + final override fun overrideModality2(): Any = "" + public override fun overrideVisibility(): Any = "" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.kt new file mode 100644 index 00000000000..7a7f94f97c0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.kt @@ -0,0 +1,29 @@ +// MODULE: m1-common +// FILE: common.kt + +open class Base() { + open fun overrideReturnType(): Any = "" + open fun overrideModality1(): Any = "" + open fun overrideModality2(): Any = "" + protected open fun overrideVisibility(): Any = "" +} + +expect open class Foo : Base { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + fun injectedMethod() {} + val injectedProperty: Int = 42 + override fun overrideReturnType(): String = "" + final override fun overrideModality1(): Any = "" + final override fun overrideModality2(): Any = "" + public override fun overrideVisibility(): Any = "" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/substitutedFakeOverrideChangedToRealOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/substitutedFakeOverrideChangedToRealOverride.kt new file mode 100644 index 00000000000..7715948d721 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/substitutedFakeOverrideChangedToRealOverride.kt @@ -0,0 +1,16 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +open class Base { + open fun foo(t: T) {} +} + +expect open class Foo : Base + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Base() { + override fun foo(t: String) {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloActualTypealias.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloActualTypealias.kt new file mode 100644 index 00000000000..ae03742f897 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloActualTypealias.kt @@ -0,0 +1,22 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +expect open class Supertype() + +expect open class Foo : Supertype { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual typealias Supertype = SupertypeImpl + +open class SupertypeImpl() + +actual open class Foo : SupertypeImpl() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias1.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias1.kt new file mode 100644 index 00000000000..1851dc4c011 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias1.kt @@ -0,0 +1,19 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +open class Supertype() +typealias SupertypeAlias = Supertype + +expect open class Foo : Supertype { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : SupertypeAlias() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias2.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias2.kt new file mode 100644 index 00000000000..a76d8ca5fde --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias2.kt @@ -0,0 +1,19 @@ +// FIR_IDENTICAL +// MODULE: m1-common +// FILE: common.kt + +open class Supertype() +typealias SupertypeAlias = Supertype + +expect open class Foo : SupertypeAlias { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Foo : Supertype() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.fir.kt new file mode 100644 index 00000000000..45e50c148ca --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.fir.kt @@ -0,0 +1,29 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun existingMethodInBase() +} + +expect open class Foo : Base { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual open class Base { + actual fun existingMethodInBase() {} + open fun injected(): Any = "" +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + override fun injected(): String = "" // covariant override +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt new file mode 100644 index 00000000000..810a4a8e8fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt @@ -0,0 +1,29 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun existingMethodInBase() +} + +expect open class Foo : Base { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual open class Base { + actual fun existingMethodInBase() {} + open fun injected(): Any = "" +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + override fun injected(): String = "" // covariant override +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.fir.kt new file mode 100644 index 00000000000..4b78f6756d3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.fir.kt @@ -0,0 +1,31 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base() { + fun existingMethodInBase(param: T) +} + +open class Transitive : Base() + +expect open class Foo : Transitive { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual open class Base { + actual fun existingMethodInBase(param: T) {} + open fun injected(param: T): Any = "" +} + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + override fun injected(param: String): String = "" // covariant override +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt new file mode 100644 index 00000000000..c332f5de492 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt @@ -0,0 +1,31 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base() { + fun existingMethodInBase(param: T) +} + +open class Transitive : Base() + +expect open class Foo : Transitive { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual open class Base { + actual fun existingMethodInBase(param: T) {} + open fun injected(param: T): Any = "" +} + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + override fun injected(param: String): String = "" // covariant override +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod.kt new file mode 100644 index 00000000000..dae360bfcf6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod.kt @@ -0,0 +1,28 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun existingMethodInBase() +} + +expect open class Foo : Base { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual open class Base { + actual fun existingMethodInBase() {} + fun injected() {} +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt new file mode 100644 index 00000000000..f390b842e10 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt @@ -0,0 +1,30 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base() { + fun existingMethodInBase(param: T) +} + +open class Transitive : Base() + +expect open class Foo : Transitive { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual open class Base { + actual fun existingMethodInBase(param: T) {} + fun injected() {} +} + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.fir.kt new file mode 100644 index 00000000000..66b8ca422a2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.fir.kt @@ -0,0 +1,24 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected() +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected() {} +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.kt new file mode 100644 index 00000000000..d604692a322 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.kt @@ -0,0 +1,24 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected() +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected() {} +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.fir.kt new file mode 100644 index 00000000000..608cee313cf --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.fir.kt @@ -0,0 +1,26 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected(param: T) +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected(param: T) {} +} + +open class Transitive : Base() + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt new file mode 100644 index 00000000000..2086a0bd07d --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt @@ -0,0 +1,26 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base { + fun injected(param: T) +} + +expect open class Foo { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual fun injected(param: T) {} +} + +open class Transitive : Base() + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride.kt new file mode 100644 index 00000000000..0368a206120 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride.kt @@ -0,0 +1,27 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base() { + open fun existingMethodInBase() +} + +expect open class Foo : Base { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual open fun existingMethodInBase() {} +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + override fun existingMethodInBase() {} // override from super +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt new file mode 100644 index 00000000000..1b6cc43d1af --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt @@ -0,0 +1,29 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base() { + open fun existingMethodInBase(param: T) +} + +open class Transitive : Base() + +expect open class Foo : Transitive { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual open class Base { + actual open fun existingMethodInBase(param: T) {} +} + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 + + override fun existingMethodInBase(param: String) {} // override from super +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt new file mode 100644 index 00000000000..8115a7a8814 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt @@ -0,0 +1,30 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base() { + fun existingMethodInBase() +} + +expect open class Foo : Base { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual typealias Base = BaseImpl + +open class BaseImpl { + fun existingMethodInBase() {} + fun injected() {} +} + +actual open class Foo : Base() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt new file mode 100644 index 00000000000..31cc41e9bc8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt @@ -0,0 +1,32 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +expect open class Base() { + fun existingMethodInBase(param: T) +} + +open class Transitive : Base() + +expect open class Foo : Transitive { + fun existingMethod() + val existingParam: Int +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual +actual typealias Base = BaseImpl + +open class BaseImpl { + fun existingMethodInBase(param: T) {} + fun injected() {} +} + +actual open class Foo : Transitive() { + actual fun existingMethod() {} + actual val existingParam: Int = 904 +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt b/compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt index 067dc4f9558..ac03cf1fb3b 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typealiasToKtLibrary.kt @@ -40,4 +40,4 @@ actual typealias MyDeprecatedNotMatch actual typealias MyDeprecatedMatch = kotlin.Deprecated -actual typealias MyAbstractIterator = AbstractIterator +actual typealias MyAbstractIterator = AbstractIterator diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/equalsOverrideInActualInterface.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/equalsOverrideInActualInterface.kt index edc9b346347..a49fcfd063e 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/equalsOverrideInActualInterface.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/equalsOverrideInActualInterface.kt @@ -2,6 +2,6 @@ expect interface Base // MODULE: m1-jvm()()(m1-common) -actual interface Base { - override fun equals(other: Any?): Boolean +actual interface Base { + override fun equals(other: Any?): Boolean } diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt index 804c086a1ae..146637415c6 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt @@ -22,16 +22,16 @@ class B actual typealias C1 = String actual typealias C2 = List actual typealias C3 = List -actual typealias C4 = MutableMap -actual typealias C5 = MutableMap +actual typealias C4 = MutableMap +actual typealias C5 = MutableMap actual typealias C51 = MutableMap actual typealias C52 = MutableMap actual typealias C53 = A> actual typealias C54 = B> -actual typealias C6 = MutableList -actual typealias C7 = MutableList -actual typealias C8 = MutableList<*> -actual typealias C9 = MutableList +actual typealias C6 = MutableList +actual typealias C7 = MutableList +actual typealias C8 = MutableList<*> +actual typealias C9 = MutableList typealias Tmp = MutableList -actual typealias C10 = Tmp +actual typealias C10 = Tmp diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.fir.kt new file mode 100644 index 00000000000..0fa39d9912f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.fir.kt @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// MODULE: m1-common +// FILE: common.kt + +expect open class Container { + internal fun internalFun() +} + +// MODULE: m2-jvm()()(m1-common) + +// FILE: foo/Foo.java + +package foo; + +public class Foo { + public final void internalFun() {} +} + +// FILE: jvm.kt + +actual typealias Container = foo.Foo diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt index 9f8b23d1e84..fa2a5b4943c 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/morePermissiveVisibilityOnActualViaTypeAlias.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER // MODULE: m1-common // FILE: common.kt @@ -14,9 +13,9 @@ expect open class Container { package foo; public class Foo { - public final void internalFun() {} // OK: internal -> public + public final void internalFun() {} } // FILE: jvm.kt -actual typealias Container = foo.Foo +actual typealias Container = foo.Foo diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt index 067ecb08938..26e641a0bfe 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt @@ -32,7 +32,7 @@ expect fun StringDemoInterface.plusK(): String // TARGET_PLATFORM: JS // FILE: StringDemoInterface.kt -actual typealias StringDemoInterface = KotlinXStringDemoInterface +actual typealias StringDemoInterface = KotlinXStringDemoInterface actual fun StringDemoInterface.plusK() = StringValue(value).plus("K").value diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/simple.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/simple.fir.kt new file mode 100644 index 00000000000..152a3326d1a --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/simple.fir.kt @@ -0,0 +1,22 @@ + +// MODULE: common +// TARGET_PLATFORM: Common +expect open class A() + +// MODULE: intermediate()()(common) +// TARGET_PLATFORM: Common +class B : A() { + fun foo(): String = "O" +} + +fun getB(): B = B() + +// MODULE: main()()(intermediate) +actual open class A actual constructor() { + fun bar(): String = "K" +} + +fun box(): String { + val b = getB() + return b.foo() + b.bar() +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/simple.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/simple.kt index fd79eff6cdc..37328b7adfe 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/hmpp/simple.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/simple.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // MODULE: common // TARGET_PLATFORM: Common @@ -13,8 +12,8 @@ class B : A() { fun getB(): B = B() // MODULE: main()()(intermediate) -actual open class A actual constructor() { - fun bar(): String = "K" +actual open class A actual constructor() { + fun bar(): String = "K" } fun box(): String { diff --git a/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.fir.kt new file mode 100644 index 00000000000..09210b9f41c --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.fir.kt @@ -0,0 +1,18 @@ +// MODULE: m1-common +// FILE: common.kt + +expect open class Foo { + open fun bar(): String +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +interface Bar { + fun bar(): String +} + +val bar: Bar + get() = null!! + +actual open class Foo : Bar by bar diff --git a/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt index 0681dd8ba6a..4ddf3ee8426 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // MODULE: m1-common // FILE: common.kt @@ -16,4 +15,4 @@ interface Bar { val bar: Bar get() = null!! -actual open class Foo : Bar by bar +actual open class Foo : Bar by bar diff --git a/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.fir.kt index f977beda2ff..f36558acf07 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.fir.kt @@ -12,4 +12,6 @@ import java.util.AbstractMap +@OptIn(kotlin.ExperimentalMultiplatform::class) +@kotlin.AllowDifferentMembersInActual public actual abstract class AbstractMutableMap() : MutableMap, AbstractMap() diff --git a/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.kt b/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.kt index b2c3ad70bd9..860c3d79026 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/implicitActualFakeOverride_AbstractMap.kt @@ -12,4 +12,6 @@ public expect abstract class AbstractMutableMap : MutableMap { import java.util.AbstractMap +@OptIn(kotlin.ExperimentalMultiplatform::class) +@kotlin.AllowDifferentMembersInActual public actual abstract class AbstractMutableMap() : MutableMap, AbstractMap() diff --git a/compiler/testData/diagnostics/tests/multiplatform/manyImplMemberNotImplemented.kt b/compiler/testData/diagnostics/tests/multiplatform/manyImplMemberNotImplemented.kt index 93f11e84637..d2fb7333aa8 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/manyImplMemberNotImplemented.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/manyImplMemberNotImplemented.kt @@ -21,18 +21,18 @@ class C : C2(), I2 // TARGET_PLATFORM: JVM // FILE: main.kt -actual open class C1 { - fun f() {} +actual open class C1 { + fun f() {} } -actual interface I1 { - fun f() {} +actual interface I1 { + fun f() {} } -actual abstract class C2 actual constructor() { - fun g() {} +actual abstract class C2 actual constructor() { + fun g() {} } -actual interface I2 { - fun g() +actual interface I2 { + fun g() } diff --git a/compiler/testData/diagnostics/tests/multiplatform/manyInterfacesMemberNotImplemented.kt b/compiler/testData/diagnostics/tests/multiplatform/manyInterfacesMemberNotImplemented.kt index db8b3d83aad..3e6160af957 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/manyInterfacesMemberNotImplemented.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/manyInterfacesMemberNotImplemented.kt @@ -16,10 +16,10 @@ class B : A() // TARGET_PLATFORM: JVM // FILE: main.kt -actual interface S1 { - fun f() {} +actual interface S1 { + fun f() {} } -actual interface S2 { - fun f() {} +actual interface S2 { + fun f() {} } diff --git a/compiler/testData/multiplatform/genericDeclarations/output.txt b/compiler/testData/multiplatform/genericDeclarations/output.txt index ce9e219309f..d2bfed57d19 100644 --- a/compiler/testData/multiplatform/genericDeclarations/output.txt +++ b/compiler/testData/multiplatform/genericDeclarations/output.txt @@ -3,6 +3,8 @@ Exit code: OK Output: -- JVM -- -Exit code: OK +Exit code: COMPILATION_ERROR Output: - +compiler/testData/multiplatform/genericDeclarations/jvm.kt:15:17: error: actual class 'AbstractList': actual class and its non-final expect class must declare exactly the same supertypes. Actual class declares the following supertypes that are not presented in expect class: 'Serializable'. This error happens because the expect class 'AbstractList' is non-final. Also see https://youtrack.jetbrains.com/issue/KT-22841 for more details +actual abstract class AbstractList : MutableList, java.io.Serializable + ^ 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 a3b6013a96d..6103642df06 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 @@ -23046,6 +23046,382 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/multiplatform/widerVisibilityInActualClassifier.kt"); } + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker") + @TestDataPath("$PROJECT_ROOT") + public class ActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker { + @Test + @TestMetadata("actualTypealias.kt") + public void testActualTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualTypealias.kt"); + } + + @Test + @TestMetadata("actualizeFakeOverridePropertyToJavaMethod.kt") + public void testActualizeFakeOverridePropertyToJavaMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeFakeOverridePropertyToJavaMethod.kt"); + } + + @Test + @TestMetadata("actualizePrimaryConstructorWithSecondaryConstructor.kt") + public void testActualizePrimaryConstructorWithSecondaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizePrimaryConstructorWithSecondaryConstructor.kt"); + } + + @Test + @TestMetadata("actualizeSecondaryConstructorWithPrimaryConstructor.kt") + public void testActualizeSecondaryConstructorWithPrimaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/actualizeSecondaryConstructorWithPrimaryConstructor.kt"); + } + + @Test + public void testAllFilesPresentInActualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); + } + + @Test + @TestMetadata("allowDifferentMembersInActual_class.kt") + public void testAllowDifferentMembersInActual_class() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_class.kt"); + } + + @Test + @TestMetadata("allowDifferentMembersInActual_typealias.kt") + public void testAllowDifferentMembersInActual_typealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/allowDifferentMembersInActual_typealias.kt"); + } + + @Test + @TestMetadata("changeClassTypeParameterNames.kt") + public void testChangeClassTypeParameterNames() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeClassTypeParameterNames.kt"); + } + + @Test + @TestMetadata("changeFunctionTypeParameterNamesInOverride.kt") + public void testChangeFunctionTypeParameterNamesInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeFunctionTypeParameterNamesInOverride.kt"); + } + + @Test + @TestMetadata("changeLateinitInOverride.kt") + public void testChangeLateinitInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeLateinitInOverride.kt"); + } + + @Test + @TestMetadata("changeModalityInOverride.kt") + public void testChangeModalityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityInOverride.kt"); + } + + @Test + @TestMetadata("changeModalityOfSubstitutedFakeOverride.kt") + public void testChangeModalityOfSubstitutedFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfSubstitutedFakeOverride.kt"); + } + + @Test + @TestMetadata("changeModalityOfToStringInOverride.kt") + public void testChangeModalityOfToStringInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityOfToStringInOverride.kt"); + } + + @Test + @TestMetadata("changeParameterNameInOverride.kt") + public void testChangeParameterNameInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeParameterNameInOverride.kt"); + } + + @Test + @TestMetadata("changeSetterVisibilityInOverride.kt") + public void testChangeSetterVisibilityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeSetterVisibilityInOverride.kt"); + } + + @Test + @TestMetadata("changeVisibilityInOverride.kt") + public void testChangeVisibilityInOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeVisibilityInOverride.kt"); + } + + @Test + @TestMetadata("covariantFunctionOverride.kt") + public void testCovariantFunctionOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantFunctionOverride.kt"); + } + + @Test + @TestMetadata("covariantOverrideGenericUpperBound.kt") + public void testCovariantOverrideGenericUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenericUpperBound.kt"); + } + + @Test + @TestMetadata("covariantOverrideGenerics.kt") + public void testCovariantOverrideGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantOverrideGenerics.kt"); + } + + @Test + @TestMetadata("covariantPropertyOverride.kt") + public void testCovariantPropertyOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/covariantPropertyOverride.kt"); + } + + @Test + @TestMetadata("fakeOverrideChangedToRealOverride.kt") + public void testFakeOverrideChangedToRealOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/fakeOverrideChangedToRealOverride.kt"); + } + + @Test + @TestMetadata("finalClassIsActualizedByOpenClass.kt") + public void testFinalClassIsActualizedByOpenClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalClassIsActualizedByOpenClass.kt"); + } + + @Test + @TestMetadata("finalMethodIsActualizedByOpenMethod.kt") + public void testFinalMethodIsActualizedByOpenMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/finalMethodIsActualizedByOpenMethod.kt"); + } + + @Test + @TestMetadata("flexibleTypesMatching.kt") + public void testFlexibleTypesMatching() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/flexibleTypesMatching.kt"); + } + + @Test + @TestMetadata("injectClass.kt") + public void testInjectClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectClass.kt"); + } + + @Test + @TestMetadata("injectContextReceiverOverload.kt") + public void testInjectContextReceiverOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectContextReceiverOverload.kt"); + } + + @Test + @TestMetadata("injectEmptySuperClass.kt") + public void testInjectEmptySuperClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectEmptySuperClass.kt"); + } + + @Test + @TestMetadata("injectExtensionReceiverOverload.kt") + public void testInjectExtensionReceiverOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectExtensionReceiverOverload.kt"); + } + + @Test + @TestMetadata("injectGenericUpperBoundOverload.kt") + public void testInjectGenericUpperBoundOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectGenericUpperBoundOverload.kt"); + } + + @Test + @TestMetadata("injectMethod_internalMethod.kt") + public void testInjectMethod_internalMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_internalMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_privateMethod.kt") + public void testInjectMethod_privateMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_privateMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_protectedMethod.kt") + public void testInjectMethod_protectedMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_protectedMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_publicMethod.kt") + public void testInjectMethod_publicMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethod.kt"); + } + + @Test + @TestMetadata("injectMethod_publicMethodInJava.kt") + public void testInjectMethod_publicMethodInJava() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectMethod_publicMethodInJava.kt"); + } + + @Test + @TestMetadata("injectParameterOverload.kt") + public void testInjectParameterOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverload.kt"); + } + + @Test + @TestMetadata("injectParameterOverloadWithGenerics.kt") + public void testInjectParameterOverloadWithGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectParameterOverloadWithGenerics.kt"); + } + + @Test + @TestMetadata("injectPrimaryConstructor.kt") + public void testInjectPrimaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrimaryConstructor.kt"); + } + + @Test + @TestMetadata("injectPrivateProperty.kt") + public void testInjectPrivateProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPrivateProperty.kt"); + } + + @Test + @TestMetadata("injectProperty.kt") + public void testInjectProperty() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectProperty.kt"); + } + + @Test + @TestMetadata("injectPropertyWithTheSameSignatureAsExistingFunction.kt") + public void testInjectPropertyWithTheSameSignatureAsExistingFunction() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPropertyWithTheSameSignatureAsExistingFunction.kt"); + } + + @Test + @TestMetadata("injectPublicFakeOverrideMethod.kt") + public void testInjectPublicFakeOverrideMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectPublicFakeOverrideMethod.kt"); + } + + @Test + @TestMetadata("injectSecondaryConstructor.kt") + public void testInjectSecondaryConstructor() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSecondaryConstructor.kt"); + } + + @Test + @TestMetadata("injectSupertype_SupertypeIsExpectActualPair.kt") + public void testInjectSupertype_SupertypeIsExpectActualPair() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair.kt"); + } + + @Test + @TestMetadata("injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt") + public void testInjectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectSupertype_SupertypeIsExpectActualPair_transitiveFakeOverride.kt"); + } + + @Test + @TestMetadata("injectVarargParameterOverload.kt") + public void testInjectVarargParameterOverload() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/injectVarargParameterOverload.kt"); + } + + @Test + @TestMetadata("nestedExpectOpenClass.kt") + public void testNestedExpectOpenClass() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/nestedExpectOpenClass.kt"); + } + + @Test + @TestMetadata("propertyKindOverride.kt") + public void testPropertyKindOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/propertyKindOverride.kt"); + } + + @Test + @TestMetadata("severalMismatches.kt") + public void testSeveralMismatches() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/severalMismatches.kt"); + } + + @Test + @TestMetadata("substitutedFakeOverrideChangedToRealOverride.kt") + public void testSubstitutedFakeOverrideChangedToRealOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/substitutedFakeOverrideChangedToRealOverride.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloActualTypealias.kt") + public void testSuperTypesAreTheSameModuloActualTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloActualTypealias.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloTypealias1.kt") + public void testSuperTypesAreTheSameModuloTypealias1() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias1.kt"); + } + + @Test + @TestMetadata("superTypesAreTheSameModuloTypealias2.kt") + public void testSuperTypesAreTheSameModuloTypealias2() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/superTypesAreTheSameModuloTypealias2.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt") + public void testSupertypeIsExpectActual_covariantOverrideOfInjectedFromSuper() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_covariantOverrideOfInjectedFromSuper_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectMethod.kt") + public void testSupertypeIsExpectActual_injectMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectMethod_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectSupertype.kt") + public void testSupertypeIsExpectActual_injectSupertype() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_injectSupertype_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_simpleOverride.kt") + public void testSupertypeIsExpectActual_simpleOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_simpleOverride_transitiveSubstitutionFakeOverride.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt") + public void testSupertypeIsExpectActual_supertypeIsActualTypealias_injectMethod() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod.kt"); + } + + @Test + @TestMetadata("supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt") + public void testSupertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/supertypeIsExpectActual_supertypeIsActualTypealias_injectMethod_transitiveSubstitutionFakeOverride.kt"); + } + } + @Nested @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/annotationMatching") @TestDataPath("$PROJECT_ROOT") diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualMemberDiff.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualMemberDiff.kt new file mode 100644 index 00000000000..3601db23b65 --- /dev/null +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/multiplatform/ExpectActualMemberDiff.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.multiplatform + +// This class will be later used by K2. That's why it's placed in compiler.common module +data class ExpectActualMemberDiff(val kind: Kind, val actualMember: M, val expectClass: C) { + /** + * Diff kinds that are legal for fake-overrides in final `expect class`, but illegal for non-final `expect class` + * + * Also see: [toDiffKind] + */ + enum class Kind(val rawMessage: String) { + NonPrivateCallableAdded( + "{0}: non-private member must be declared in the expect class as well. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + ReturnTypeChangedInOverride( + "{0}: the return type of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + ModalityChangedInOverride( + "{0}: the modality of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + VisibilityChangedInOverride( + "{0}: the visibility of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + SetterVisibilityChangedInOverride( + "{0}: the setter visibility of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + ParameterNameChangedInOverride( + "{0}: the parameter names of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + PropertyKindChangedInOverride( + "{0}: the property kind (val vs var) of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + LateinitChangedInOverride( + "{0}: the property modifiers (lateinit) of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + TypeParameterNamesChangedInOverride( + "{0}: the type parameter names of this member must be the same in the expect class and the actual class. " + + "This error happens because the expect class ''{1}'' is non-final" + ), + } +} + +/** + * This function serves a purpose of type-safe documentation. A mapping can be established between [ExpectActualCompatibility.Incompatible] + * and [ExpectActualMemberDiff.Kind]. This exhaustive when fixates this mapping, ensuring that we won't forget to add new + * [ExpectActualMemberDiff.Kind] when [ExpectActualCompatibility.Incompatible] is updated. + */ +@Suppress("unused") // The function is a documentation. That's why it's unused +private fun ExpectActualCompatibility.Incompatible<*>.toDiffKind(): ExpectActualMemberDiff.Kind? = when (this) { + ExpectActualCompatibility.Incompatible.CallableKind -> ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + ExpectActualCompatibility.Incompatible.ParameterCount -> ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + ExpectActualCompatibility.Incompatible.ParameterShape -> ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + ExpectActualCompatibility.Incompatible.ParameterTypes -> ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + ExpectActualCompatibility.Incompatible.ReturnType -> ExpectActualMemberDiff.Kind.ReturnTypeChangedInOverride + ExpectActualCompatibility.Incompatible.FunctionTypeParameterCount -> ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + ExpectActualCompatibility.Incompatible.ClassTypeParameterCount -> null // Not applicable because ExpectActualMemberDiff is about members + ExpectActualCompatibility.Incompatible.FunctionTypeParameterUpperBounds -> ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + ExpectActualCompatibility.Incompatible.ClassTypeParameterUpperBounds -> null // Not applicable because ExpectActualMemberDiff is about members + ExpectActualCompatibility.Incompatible.ActualFunctionWithDefaultParameters -> null // It's not possible to add default parameters in override + ExpectActualCompatibility.Incompatible.ClassKind -> null // Not applicable because ExpectActualMemberDiff is about members + ExpectActualCompatibility.Incompatible.ClassModifiers -> null // Not applicable because ExpectActualMemberDiff is about members + is ExpectActualCompatibility.Incompatible.ClassScopes -> null // Not applicable because ExpectActualMemberDiff is about members + ExpectActualCompatibility.Incompatible.EnumEntries -> null // Not applicable because ExpectActualMemberDiff is about members + ExpectActualCompatibility.Incompatible.FunInterfaceModifier -> null // Not applicable because ExpectActualMemberDiff is about members + ExpectActualCompatibility.Incompatible.FunctionModifiersDifferent -> null // It's not possible to override with different function modifier + ExpectActualCompatibility.Incompatible.FunctionModifiersNotSubset -> null // It's not possible to override with different function modifier + ExpectActualCompatibility.Incompatible.Modality -> ExpectActualMemberDiff.Kind.ModalityChangedInOverride + ExpectActualCompatibility.Incompatible.ParameterNames -> ExpectActualMemberDiff.Kind.ParameterNameChangedInOverride + ExpectActualCompatibility.Incompatible.PropertyConstModifier -> null // const fun can't be overridden + ExpectActualCompatibility.Incompatible.PropertyKind -> ExpectActualMemberDiff.Kind.PropertyKindChangedInOverride + ExpectActualCompatibility.Incompatible.PropertyLateinitModifier -> ExpectActualMemberDiff.Kind.LateinitChangedInOverride + ExpectActualCompatibility.Incompatible.PropertySetterVisibility -> ExpectActualMemberDiff.Kind.SetterVisibilityChangedInOverride + ExpectActualCompatibility.Incompatible.Supertypes -> null // Not applicable because ExpectActualMemberDiff is about members. But related: ACTUAL_CLASSIFIER_MUST_HAVE_THE_SAME_SUPERTYPES_AS_NON_FINAL_EXPECT_CLASSIFIER + ExpectActualCompatibility.Incompatible.TypeParameterNames -> ExpectActualMemberDiff.Kind.TypeParameterNamesChangedInOverride + ExpectActualCompatibility.Incompatible.TypeParameterReified -> null // inline fun can't be overridden + ExpectActualCompatibility.Incompatible.TypeParameterVariance -> null // Members are not allowed to have variance + ExpectActualCompatibility.Incompatible.Unknown -> null // Unknown incompatibility is never reported + ExpectActualCompatibility.Incompatible.ValueParameterCrossinline -> null // inline fun can't be overridden + ExpectActualCompatibility.Incompatible.ValueParameterNoinline -> null // inline fun can't be overridden + ExpectActualCompatibility.Incompatible.ValueParameterVararg -> ExpectActualMemberDiff.Kind.NonPrivateCallableAdded + ExpectActualCompatibility.Incompatible.Visibility -> ExpectActualMemberDiff.Kind.VisibilityChangedInOverride +} diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt index 624013db688..4d847cae05f 100644 --- a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt @@ -10,6 +10,7 @@ package kotlin.reflect * * @param R return type of the callable. */ +@AllowDifferentMembersInActual // New 'KAnnotatedElement` supertype is added compared to the expect declaration public actual interface KCallable : KAnnotatedElement { /** * The name of this callable as it was declared in the source code. diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClass.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClass.kt index d6906cc0903..d6f6f79d517 100644 --- a/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClass.kt +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/reflect/KClass.kt @@ -13,6 +13,7 @@ package kotlin.reflect * * @param T the type of the class. */ +@AllowDifferentMembersInActual // New 'KDeclarationContainer', 'KAnnotatedElement` supertypes are added compared to the expect declaration public actual interface KClass : KDeclarationContainer, KAnnotatedElement, KClassifier { /** * The simple name of the class as it was declared in the source code, @@ -43,7 +44,7 @@ public actual interface KClass : KDeclarationContainer, KAnnotatedEleme * For example, on JVM, [KClass] instances for a primitive type (`int`) and the corresponding wrapper type (`java.lang.Integer`) * are considered equal, because they have the same fully qualified name "kotlin.Int". */ - override fun equals(other: Any?): Boolean + actual override fun equals(other: Any?): Boolean // KT-24971 - override fun hashCode(): Int + actual override fun hashCode(): Int // KT-24971 } diff --git a/libraries/stdlib/api/js/kotlin.kt b/libraries/stdlib/api/js/kotlin.kt index be18f3cc54b..9d293e14757 100644 --- a/libraries/stdlib/api/js/kotlin.kt +++ b/libraries/stdlib/api/js/kotlin.kt @@ -846,6 +846,15 @@ public inline fun kotlin.Short.toUShort(): kotlin.UShort @kotlin.internal.InlineOnly public inline fun T.use(block: (T) -> R): R +@kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.TYPEALIAS}) +@kotlin.annotation.MustBeDocumented +@kotlin.ExperimentalMultiplatform +@kotlin.SinceKotlin(version = "1.9") +public final annotation class AllowDifferentMembersInActual : kotlin.Annotation { + public constructor AllowDifferentMembersInActual() +} + public interface Annotation { } diff --git a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt index 5d52027b687..dd4169c4166 100644 --- a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt +++ b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableCollection.kt @@ -12,6 +12,7 @@ package kotlin.collections * * @param E the type of elements contained in the collection. The collection is invariant in its element type. */ +@AllowDifferentMembersInActual // New 'checkIsMutable', 'toJSON', etc. members are added compared to the expect declaration public actual abstract class AbstractMutableCollection protected actual constructor() : AbstractCollection(), MutableCollection { actual abstract override fun add(element: E): Boolean diff --git a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt index bb8c65944d9..153a9a96ae8 100644 --- a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt +++ b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableList.kt @@ -17,6 +17,7 @@ package kotlin.collections * * @param E the type of elements contained in the list. The list is invariant in its element type. */ +@AllowDifferentMembersInActual // New 'removeRange', 'checkIsMutable', etc. members are added compared to the expect declaration public actual abstract class AbstractMutableList protected actual constructor() : AbstractMutableCollection(), MutableList { protected var modCount: Int = 0 diff --git a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt index 36cbaeaa421..8f48c9a3a10 100644 --- a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt +++ b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableMap.kt @@ -18,6 +18,7 @@ package kotlin.collections * @param K the type of map keys. The map is invariant in its key type. * @param V the type of map values. The map is invariant in its value type. */ +@AllowDifferentMembersInActual // New 'createKeysView', 'checkIsMutable', etc. members are added compared to the expect declaration public actual abstract class AbstractMutableMap protected actual constructor() : AbstractMap(), MutableMap { internal open fun createKeysView(): MutableSet = HashMapKeysDefault(this) diff --git a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableSet.kt b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableSet.kt index 42c8df2cef0..2065107c55d 100644 --- a/libraries/stdlib/js/src/kotlin/collections/AbstractMutableSet.kt +++ b/libraries/stdlib/js/src/kotlin/collections/AbstractMutableSet.kt @@ -9,6 +9,7 @@ package kotlin.collections * * @param E the type of elements contained in the set. The set is invariant in its element type. */ +@AllowDifferentMembersInActual // New 'AbstractMutableCollection` supertype is added compared to the expect declaration public actual abstract class AbstractMutableSet protected actual constructor() : AbstractMutableCollection(), MutableSet { /** diff --git a/libraries/stdlib/js/src/kotlin/reflect/KClass.kt b/libraries/stdlib/js/src/kotlin/reflect/KClass.kt index 9a0f78fc21a..680ab5dc75d 100644 --- a/libraries/stdlib/js/src/kotlin/reflect/KClass.kt +++ b/libraries/stdlib/js/src/kotlin/reflect/KClass.kt @@ -47,7 +47,7 @@ public actual interface KClass : KClassifier { * For example, on JVM, [KClass] instances for a primitive type (`int`) and the corresponding wrapper type (`java.lang.Integer`) * are considered equal, because they have the same fully qualified name "kotlin.Int". */ - override fun equals(other: Any?): Boolean + actual override fun equals(other: Any?): Boolean - override fun hashCode(): Int + actual override fun hashCode(): Int } diff --git a/libraries/stdlib/jvm/runtime/kotlin/TypeAliases.kt b/libraries/stdlib/jvm/runtime/kotlin/TypeAliases.kt index 4a7cc770ad6..24c57b92e8a 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/TypeAliases.kt +++ b/libraries/stdlib/jvm/runtime/kotlin/TypeAliases.kt @@ -28,4 +28,6 @@ package kotlin @Suppress("NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS") @SinceKotlin("1.3") public actual typealias ConcurrentModificationException = java.util.ConcurrentModificationException +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual // New 'reversed', 'thenComparing', etc. members are added compared to the expect declaration @SinceKotlin("1.1") public actual typealias Comparator = java.util.Comparator diff --git a/libraries/stdlib/jvm/runtime/kotlin/text/TypeAliases.kt b/libraries/stdlib/jvm/runtime/kotlin/text/TypeAliases.kt index d71ea556b50..79ae2d6bed4 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/text/TypeAliases.kt +++ b/libraries/stdlib/jvm/runtime/kotlin/text/TypeAliases.kt @@ -7,6 +7,8 @@ package kotlin.text +@OptIn(ExperimentalMultiplatform::class) +@AllowDifferentMembersInActual // New 'append' members are added compared to the expect declaration @SinceKotlin("1.1") public actual typealias Appendable = java.lang.Appendable @Suppress("ACTUAL_WITHOUT_EXPECT") // TODO: some supertypes are missing diff --git a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableCollection.kt b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableCollection.kt index 0d0539639b0..ff3b1e00d5c 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableCollection.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableCollection.kt @@ -13,6 +13,7 @@ import java.util.AbstractCollection * @param E the type of elements contained in the collection. The collection is invariant in its element type. */ @SinceKotlin("1.1") +@AllowDifferentMembersInActual // New 'AbstractCollection` supertype is added compared to the expect declaration public actual abstract class AbstractMutableCollection protected actual constructor() : MutableCollection, AbstractCollection() { /** * Adds the specified element to the collection. diff --git a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableList.kt b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableList.kt index 1290ad7b0b2..8c04dbf6b24 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableList.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableList.kt @@ -13,6 +13,7 @@ import java.util.AbstractList * @param E the type of elements contained in the list. The list is invariant in its element type. */ @SinceKotlin("1.1") +@AllowDifferentMembersInActual // New 'AbstractList` supertype is added compared to the expect declaration public actual abstract class AbstractMutableList protected actual constructor() : MutableList, AbstractList() { /** * Replaces the element at the specified position in this list with the specified element. diff --git a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableMap.kt b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableMap.kt index 7d7d9676c17..267c0db9d15 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableMap.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableMap.kt @@ -16,6 +16,7 @@ import java.util.AbstractMap * @param V the type of map values. The map is invariant in its value type. */ @SinceKotlin("1.1") +@AllowDifferentMembersInActual // New 'AbstractMap` supertype is added compared to the expect declaration public actual abstract class AbstractMutableMap protected actual constructor() : MutableMap, AbstractMap() { /** * Associates the specified [value] with the specified [key] in the map. diff --git a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableSet.kt b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableSet.kt index 7707b8a44db..f6ad33fdaf9 100644 --- a/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableSet.kt +++ b/libraries/stdlib/jvm/src/kotlin/collections/AbstractMutableSet.kt @@ -13,6 +13,7 @@ import java.util.AbstractSet * @param E the type of elements contained in the set. The set is invariant in its element type. */ @SinceKotlin("1.1") +@AllowDifferentMembersInActual // New 'AbstractSet` supertype is added compared to the expect declaration public actual abstract class AbstractMutableSet protected actual constructor() : MutableSet, AbstractSet() { /** * Adds the specified element to the set. diff --git a/libraries/stdlib/jvm/src/kotlin/reflect/KCallable.kt b/libraries/stdlib/jvm/src/kotlin/reflect/KCallable.kt index e38b5122481..585cc591e99 100644 --- a/libraries/stdlib/jvm/src/kotlin/reflect/KCallable.kt +++ b/libraries/stdlib/jvm/src/kotlin/reflect/KCallable.kt @@ -10,6 +10,7 @@ package kotlin.reflect * * @param R return type of the callable. */ +@AllowDifferentMembersInActual // New 'KAnnotatedElement` supertype is added compared to the expect declaration public actual interface KCallable : KAnnotatedElement { /** * The name of this callable as it was declared in the source code. diff --git a/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt b/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt index 3a2453b32aa..89043e2925f 100644 --- a/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt +++ b/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt @@ -13,6 +13,7 @@ package kotlin.reflect * * @param T the type of the class. */ +@AllowDifferentMembersInActual // KClass for JVM adds a lot of new members compared to the expect declaration public actual interface KClass : KDeclarationContainer, KAnnotatedElement, KClassifier { /** * The simple name of the class as it was declared in the source code, @@ -151,7 +152,7 @@ public actual interface KClass : KDeclarationContainer, KAnnotatedEleme * For example, on JVM, [KClass] instances for a primitive type (`int`) and the corresponding wrapper type (`java.lang.Integer`) * are considered equal, because they have the same fully qualified name "kotlin.Int". */ - override fun equals(other: Any?): Boolean + actual override fun equals(other: Any?): Boolean // KT-24971 - override fun hashCode(): Int + actual override fun hashCode(): Int // KT-24971 } diff --git a/libraries/stdlib/jvm/src/kotlin/reflect/KFunction.kt b/libraries/stdlib/jvm/src/kotlin/reflect/KFunction.kt index 41c9c2d25bb..885cd0c68f9 100644 --- a/libraries/stdlib/jvm/src/kotlin/reflect/KFunction.kt +++ b/libraries/stdlib/jvm/src/kotlin/reflect/KFunction.kt @@ -8,6 +8,7 @@ package kotlin.reflect /** * Represents a function with introspection capabilities. */ +@AllowDifferentMembersInActual // KFunction for JVM adds a lot of new members compared to the expect declaration public actual interface KFunction : KCallable, Function { /** * `true` if this function is `inline`. diff --git a/libraries/stdlib/jvm/src/kotlin/reflect/KProperty.kt b/libraries/stdlib/jvm/src/kotlin/reflect/KProperty.kt index 1f65afcef55..67f8a10493b 100644 --- a/libraries/stdlib/jvm/src/kotlin/reflect/KProperty.kt +++ b/libraries/stdlib/jvm/src/kotlin/reflect/KProperty.kt @@ -15,6 +15,7 @@ package kotlin.reflect * * @param V the type of the property value. */ +@AllowDifferentMembersInActual // KProperty for JVM adds new members compared to the expect declaration public actual interface KProperty : KCallable { /** * `true` if this property is `lateinit`. @@ -56,6 +57,7 @@ public actual interface KProperty : KCallable { /** * Represents a property declared as a `var`. */ +@AllowDifferentMembersInActual // New 'setter' member is added compared to the expect declaration public actual interface KMutableProperty : KProperty { /** The setter of this mutable property, used to change the value of the property. */ public val setter: Setter @@ -72,6 +74,7 @@ public actual interface KMutableProperty : KProperty { * Such property is either originally declared in a receiverless context such as a package, * or has the receiver bound to it. */ +@AllowDifferentMembersInActual // New 'getDelegate' and 'getter' members are added compared to the expect declaration public actual interface KProperty0 : KProperty, () -> V { /** * Returns the current value of the property. @@ -99,6 +102,7 @@ public actual interface KProperty0 : KProperty, () -> V { /** * Represents a `var`-property without any kind of receiver. */ +@AllowDifferentMembersInActual // Covariant 'setter' override. The annotations can be dropped in K2 KT-61184 public actual interface KMutableProperty0 : KProperty0, KMutableProperty { /** * Modifies the value of the property. @@ -124,6 +128,7 @@ public actual interface KMutableProperty0 : KProperty0, KMutableProperty : KProperty, (T) -> V { /** * Returns the current value of the property. @@ -164,6 +169,7 @@ public actual interface KProperty1 : KProperty, (T) -> V { /** * Represents a `var`-property, operations on which take one receiver as a parameter. */ +@AllowDifferentMembersInActual // Covariant 'setter' override. The annotations can be dropped in K2 KT-61184 public actual interface KMutableProperty1 : KProperty1, KMutableProperty { /** * Modifies the value of the property. @@ -196,6 +202,7 @@ public actual interface KMutableProperty1 : KProperty1, KMutableProp * the type of the extension receiver. * @param V the type of the property value. */ +@AllowDifferentMembersInActual // New 'getDelegate' and 'getter' members are added compared to the expect declaration public actual interface KProperty2 : KProperty, (D, E) -> V { /** * Returns the current value of the property. In case of the extension property in a class, @@ -236,6 +243,7 @@ public actual interface KProperty2 : KProperty, (D, E) -> V { /** * Represents a `var`-property, operations on which take two receivers as parameters. */ +@AllowDifferentMembersInActual // Covariant 'setter' override. The annotations can be dropped in K2 KT-61184 public actual interface KMutableProperty2 : KProperty2, KMutableProperty { /** * Modifies the value of the property. diff --git a/libraries/stdlib/jvm/src/kotlin/reflect/KType.kt b/libraries/stdlib/jvm/src/kotlin/reflect/KType.kt index 742c89e5cf2..f56bbd7275a 100644 --- a/libraries/stdlib/jvm/src/kotlin/reflect/KType.kt +++ b/libraries/stdlib/jvm/src/kotlin/reflect/KType.kt @@ -9,6 +9,7 @@ package kotlin.reflect * Represents a type. Type is usually either a class with optional type arguments, * or a type parameter of some declaration, plus nullability. */ +@AllowDifferentMembersInActual // New 'KAnnotatedElement` supertype is added compared to the expect declaration public actual interface KType : KAnnotatedElement { /** * The declaration of the classifier used in this type. diff --git a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableCollection.kt b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableCollection.kt index 0bcba06c9ed..f1984fc6bb3 100644 --- a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableCollection.kt +++ b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableCollection.kt @@ -10,6 +10,7 @@ package kotlin.collections * * @param E the type of elements contained in the collection. The collection is invariant in its element type. */ +@AllowDifferentMembersInActual // New 'AbstractCollection` supertype is added compared to the expect declaration public actual abstract class AbstractMutableCollection protected actual constructor(): MutableCollection, AbstractCollection() { // Bulk Modification Operations diff --git a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableList.kt b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableList.kt index 61eb0d9889c..ffe371aa4e3 100644 --- a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableList.kt +++ b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableList.kt @@ -17,6 +17,7 @@ package kotlin.collections * * @param E the type of elements contained in the list. The list is invariant in its element type. */ +@AllowDifferentMembersInActual // New 'removeRange', 'modCount' members are added compared to the expect declaration public actual abstract class AbstractMutableList protected actual constructor() : AbstractMutableCollection(), MutableList { /** * The number of times this list is structurally modified. diff --git a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableMap.kt b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableMap.kt index 560223d93f3..93f05543774 100644 --- a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableMap.kt +++ b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableMap.kt @@ -8,6 +8,7 @@ package kotlin.collections * @param K the type of map keys. The map is invariant in its key type. * @param V the type of map values. The map is invariant in its value type. */ +@AllowDifferentMembersInActual // New 'AbstractMap` supertype is added compared to the expect declaration @SinceKotlin("1.1") public actual abstract class AbstractMutableMap protected actual constructor() : AbstractMap(), MutableMap { /** diff --git a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableSet.kt b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableSet.kt index 47da186ccb6..bbcac4168fa 100644 --- a/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableSet.kt +++ b/libraries/stdlib/native-wasm/src/kotlin/collections/AbstractMutableSet.kt @@ -5,6 +5,7 @@ package kotlin.collections * * @param E the type of elements contained in the set. The set is invariant in its element type. */ +@AllowDifferentMembersInActual // New 'AbstractMutableCollection` supertype is added compared to the expect declaration @SinceKotlin("1.1") public actual abstract class AbstractMutableSet protected actual constructor() : AbstractMutableCollection(), MutableSet { /** diff --git a/libraries/stdlib/src/kotlin/annotations/AllowDifferentMembersInActual.kt b/libraries/stdlib/src/kotlin/annotations/AllowDifferentMembersInActual.kt new file mode 100644 index 00000000000..1bbe9a19175 --- /dev/null +++ b/libraries/stdlib/src/kotlin/annotations/AllowDifferentMembersInActual.kt @@ -0,0 +1,37 @@ +package kotlin + +import kotlin.annotation.AnnotationTarget.* + +/** + * Kotlin reports a compilation error for cases when non-final `expect class` and its counterpart `actual class` have different set of + * non-private members (e.g. when a new member declared in `actual class` that wasn't presented in its `expect class`, or when + * modality is different). + * + * By marking `actual class` with this annotation, you suppress the compilation error mentioned above. + * + * ## Safety Risks + * + * Using this annotation causes undefined behaviour, it's not known what can break because of that. Be prepared that at some point this + * annotation might become deprecated, and you'd need to migrate your code. + * + * If you use this annotation and can't migrate, consider describing your use cases in + * [KT-22841](https://youtrack.jetbrains.com/issue/KT-22841) comments. + * + * ## Migration + * + * Please consider the following alternatives: + * - Make members in `expect class` and `actual class` the same + * - If the member was declared only in `actual class` then you'd need to declare it in the `expect class` as well + * - If the member is already declared in the `expect class` then make sure that the member is the same in the `actual class` (modality is + * the same, visibility is the same, return type is the same, etc.) + * - Make the `expect class` `final`. You might need to rewrite your code to use composition instead of inheritance. + * - Mark the members under the question as `private` + * + * [AllowDifferentMembersInActual] is supposed to be used for the transition period. + */ +@Retention(AnnotationRetention.SOURCE) +@Target(CLASS, TYPEALIAS) +@MustBeDocumented +@ExperimentalMultiplatform +@SinceKotlin("1.9") +public annotation class AllowDifferentMembersInActual diff --git a/libraries/stdlib/src/kotlin/reflect/KClass.kt b/libraries/stdlib/src/kotlin/reflect/KClass.kt index f675514cffd..47ec6fba6a8 100644 --- a/libraries/stdlib/src/kotlin/reflect/KClass.kt +++ b/libraries/stdlib/src/kotlin/reflect/KClass.kt @@ -32,4 +32,7 @@ public expect interface KClass : KClassifier { @SinceKotlin("1.1") public fun isInstance(value: Any?): Boolean + override fun equals(other: Any?): Boolean // KT-24971 + + override fun hashCode(): Int // KT-24971 } \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt index 2251a80db6f..2351fb3daad 100644 --- a/libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt @@ -32,4 +32,7 @@ public actual interface KClass : KClassifier { @SinceKotlin("1.1") public actual fun isInstance(value: Any?): Boolean + actual override fun equals(other: Any?): Boolean // KT-24971 + + actual override fun hashCode(): Int // KT-24971 } \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt index cf5a401ab38..593800ef720 100644 --- a/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt @@ -15,6 +15,9 @@ internal object NothingKClassImpl : KClass { override val qualifiedName: String get() = "kotlin.Nothing" override fun isInstance(value: Any?): Boolean = false + + override fun equals(other: Any?): Boolean = super.equals(other) // KT-24971 + override fun hashCode(): Int = super.hashCode() // KT-24971 } internal object ErrorKClass : KClass { @@ -22,6 +25,9 @@ internal object ErrorKClass : KClass { override val qualifiedName: String get() = error("Unknown qualifiedName for ErrorKClass") override fun isInstance(value: Any?): Boolean = error("Can's check isInstance on ErrorKClass") + + override fun equals(other: Any?): Boolean = super.equals(other) // KT-24971 + override fun hashCode(): Int = super.hashCode() // KT-24971 } internal class KClassImpl(internal val typeData: TypeInfoData) : KClass { diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index 6421e1703c0..abd1d0066d9 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -1,3 +1,6 @@ +public abstract interface annotation class kotlin/AllowDifferentMembersInActual : java/lang/annotation/Annotation { +} + public abstract interface annotation class kotlin/BuilderInference : java/lang/annotation/Annotation { }