diff --git a/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt b/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt index d545c3a191c..be497b7c962 100644 --- a/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt +++ b/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt @@ -9,6 +9,22 @@ object AnalysisFlags { @JvmStatic val skipMetadataVersionCheck by AnalysisFlag.Delegates.Boolean + /** + * Metadata compilation is run for every non-platform fragment (for common and intermediate fragments). + * + * The initial purpose of the metadata compilation is to produce metadata artifacts for non-platform source sets. + * These metadata artifacts are needed only for IDE. + * + * But metadata compilation is also used to report diagnostics when regular compilation can't do that for whatever reason (My opinion, + * that the reason is broken design of `expect`/`actual` KT-64130). + * E.g. `ABSTRACT_NOT_IMPLEMENTED` (KT-66205) + * + * This flag is true in two case: + * 1. Metadata compilation (`:compile*KotlinMetadata` Gradle task) + * 2. IDE analysis + * + * Known metadata compilation problems: KT-66382 + */ @JvmStatic val metadataCompilation by AnalysisFlag.Delegates.Boolean diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt index b99e48d1328..feaca4a1e9c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonDeclarationCheckers.kt @@ -100,8 +100,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() { get() = setOf( FirOverrideChecker.Regular, FirOverrideChecker.ForExpectClass, - FirNotImplementedOverrideChecker.Regular, - FirNotImplementedOverrideChecker.ForExpectClass, + FirNotImplementedOverrideChecker, FirNotImplementedOverrideSimpleEnumEntryChecker.Regular, FirNotImplementedOverrideSimpleEnumEntryChecker.ForExpectClass, FirThrowableSubclassChecker, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt index ef91686b64e..d12d7090f45 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirNotImplementedOverrideChecker.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtFakeSourceElementKind +import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.diagnostics.DiagnosticReporter @@ -41,22 +42,9 @@ import org.jetbrains.kotlin.util.ImplementationStatus import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract -sealed class FirNotImplementedOverrideChecker(mppKind: MppCheckerKind) : FirClassChecker(mppKind) { - object Regular : FirNotImplementedOverrideChecker(MppCheckerKind.Platform) { - override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { - if (declaration.isExpect) return - super.check(declaration, context, reporter) - } - } - - object ForExpectClass : FirNotImplementedOverrideChecker(MppCheckerKind.Common) { - override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { - if (!declaration.isExpect) return - super.check(declaration, context, reporter) - } - } - +object FirNotImplementedOverrideChecker : FirClassChecker(MppCheckerKind.Platform) { override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) { + if (declaration.isExpect && !context.languageVersionSettings.getFlag(AnalysisFlags.metadataCompilation)) return val source = declaration.source ?: return val sourceKind = source.kind if (sourceKind is KtFakeSourceElementKind && sourceKind != KtFakeSourceElementKind.EnumInitializer) return diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.fir.kt index d30683a55e6..5d4d26ee81d 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.fir.kt @@ -5,7 +5,7 @@ interface Base { fun foo() } -expect open class Foo : Base +expect open class Foo : Base // MODULE: m2-jvm()()(m1-common) // FILE: jvm.kt diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.ll.kt new file mode 100644 index 00000000000..2aeac3eb798 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.ll.kt @@ -0,0 +1,15 @@ +// MODULE: m1-common +// FILE: common.kt + +interface Base { + 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/changeModalityFromAbstractToOpenInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.fir.kt index 44a8809f154..e5197f5049e 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.fir.kt @@ -3,7 +3,7 @@ interface Base { fun foo() } -expect open class Foo() : Base +expect open class Foo() : Base // MODULE: m2-jvm()()(m1-common) diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.ll.kt new file mode 100644 index 00000000000..fedc2b100b1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.ll.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt +interface Base { + fun foo() +} +expect open class Foo() : Base + + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +// Mismatched scope must be reported here. But it's false negative checker in K1. +// For some reason, K1 says that modality of `exect_Foo.foo` is `abstract`. +// https://youtrack.jetbrains.com/issue/KT-59739 +actual open class Foo : Base { + override fun foo() {} +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/expectAbstractToString.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/expectAbstractToString.fir.kt index 33bb99a5dca..6cf5484e8af 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/expectAbstractToString.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/expectAbstractToString.fir.kt @@ -6,9 +6,9 @@ interface B { override fun toString(): String } -expect value class C(val s: String) : B +expect value class C(val s: String) : B -expect value class D(val s: String) : B +expect value class D(val s: String) : B // MODULE: m1-jvm()()(m1-common) // FILE: jvm.kt diff --git a/compiler/testData/diagnostics/tests/multiplatform/expectAbstractToString.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/expectAbstractToString.ll.kt new file mode 100644 index 00000000000..1bfac5565ff --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/expectAbstractToString.ll.kt @@ -0,0 +1,22 @@ +// WITH_STDLIB +// MODULE: m1-common +// FILE: common.kt + +interface B { + override fun toString(): String +} + +expect value class C(val s: String) : B + +expect value class D(val s: String) : B + +// MODULE: m1-jvm()()(m1-common) +// FILE: jvm.kt + +@JvmInline +actual value class C(actual val s: String) : B { + override fun toString(): String = s +} + +@JvmInline +actual value class D(actual val s: String) : B diff --git a/compiler/testData/diagnostics/tests/multiplatform/expectObjectWithAbstractMember.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/expectObjectWithAbstractMember.fir.kt index 409bdae712a..7ae3a5f863a 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/expectObjectWithAbstractMember.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/expectObjectWithAbstractMember.fir.kt @@ -5,7 +5,7 @@ interface Base { fun foo() } -expect object Implementation : Base +expect object Implementation : Base // MODULE: m1-jvm()()(m1-common) // FILE: jvm.kt diff --git a/compiler/testData/diagnostics/tests/multiplatform/expectObjectWithAbstractMember.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/expectObjectWithAbstractMember.ll.kt new file mode 100644 index 00000000000..aa9fc045911 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/expectObjectWithAbstractMember.ll.kt @@ -0,0 +1,17 @@ +// MODULE: m1-common +// FILE: common.kt + +interface Base { + fun foo() +} + +expect object Implementation : Base + +// MODULE: m1-jvm()()(m1-common) +// FILE: jvm.kt + +abstract class RealImplementation : Base { + override fun foo() {} +} + +actual object Implementation : RealImplementation(), Base diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.fir.kt index 04f030a55b4..e1f6bad23c0 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.fir.kt @@ -5,13 +5,13 @@ interface Foo { fun foo() } -expect class ImplicitFoo : Foo +expect class ImplicitFoo : Foo expect class ExplicitFoo : Foo { override fun foo() } -expect class ImplicitFooCheck : Foo +expect class ImplicitFooCheck : Foo // MODULE: m2-jvm()()(m1-common) // FILE: jvm.kt diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.ll.kt new file mode 100644 index 00000000000..70978a22306 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.ll.kt @@ -0,0 +1,27 @@ +// MODULE: m1-common +// FILE: common.kt + +interface Foo { + fun foo() +} + +expect class ImplicitFoo : Foo + +expect class ExplicitFoo : Foo { + override fun foo() +} + +expect class ImplicitFooCheck : Foo + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual class ImplicitFoo : Foo { + override fun foo() {} +} + +actual class ExplicitFoo : Foo { + actual override fun foo() {} +} + +actual class ImplicitFooCheck : Foo diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.fir.kt index 225bcd57efe..2f4cdb9c06f 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.fir.kt @@ -4,7 +4,7 @@ expect abstract class BaseA() { abstract fun foo() } -expect open class BaseAImpl() : BaseA +expect open class BaseAImpl() : BaseA class DerivedA1 : BaseAImpl() class DerivedA2 : BaseAImpl() { @@ -16,7 +16,7 @@ class DerivedA2 : BaseAImpl() { expect interface BaseB { fun foo() } -expect open class BaseBImpl() : BaseB +expect open class BaseBImpl() : BaseB class DerivedB1 : BaseBImpl() class DerivedB2 : BaseBImpl() { @@ -58,7 +58,7 @@ sealed class BaseEImpl() : BaseE { expect interface BaseF { fun foo() } -expect class BaseFImpl() : BaseF +expect class BaseFImpl() : BaseF diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.ll.kt index 807affa7d9f..896e0f8dbe6 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.ll.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.ll.kt @@ -4,7 +4,7 @@ expect abstract class BaseA() { abstract fun foo() } -expect open class BaseAImpl() : BaseA +expect open class BaseAImpl() : BaseA class DerivedA1 : BaseAImpl() class DerivedA2 : BaseAImpl() { @@ -16,7 +16,7 @@ class DerivedA2 : BaseAImpl() { expect interface BaseB { fun foo() } -expect open class BaseBImpl() : BaseB +expect open class BaseBImpl() : BaseB class DerivedB1 : BaseBImpl() class DerivedB2 : BaseBImpl() { @@ -58,7 +58,7 @@ sealed class BaseEImpl() : BaseE { expect interface BaseF { fun foo() } -expect class BaseFImpl() : BaseF +expect class BaseFImpl() : BaseF diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.fir.kt index 4b4f42f8e6d..196c7503cdb 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.fir.kt @@ -5,7 +5,7 @@ expect abstract class Base { abstract fun foo() } -expect class DerivedImplicit : Base +expect class DerivedImplicit : Base expect class DerivedExplicit : Base { override fun foo() diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.ll.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.ll.kt new file mode 100644 index 00000000000..e49d1b61c91 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.ll.kt @@ -0,0 +1,35 @@ +// MODULE: m1-common +// FILE: common.kt + +expect abstract class Base { + abstract fun foo() +} + +expect class DerivedImplicit : Base + +expect class DerivedExplicit : Base { + override fun foo() +} + +expect class DerivedExplicitCheck : Base { + override fun foo() +} + +// MODULE: m2-jvm()()(m1-common) +// FILE: jvm.kt + +actual abstract class Base { + actual abstract fun foo() +} + +actual class DerivedImplicit : Base() { + override fun foo() {} +} + +actual class DerivedExplicit : Base() { + actual override fun foo() {} +} + +actual class DerivedExplicitCheck : Base() { + override fun foo() {} +}