From 373abbde5df1644b8eabc02a164a6fd2dbcbba33 Mon Sep 17 00:00:00 2001 From: Nikita Bobko Date: Thu, 24 Aug 2023 18:55:49 +0200 Subject: [PATCH] Partially revert "[FE] Stop ignoring ABSTRACT_MEMBER_NOT_IMPLEMENTED for expect classes" ^KT-61039 Fixed KT-59739 is now open for K1 (but fixed in K2) Review: https://jetbrains.team/p/kt/reviews/11867/timeline This partially reverts commit 4f3ecedbca9f0220a47b470551c8d013605b4bd4. Only K1 part is reverted. Motivation for revert: KT-59739 cannot be properly fixed in K1 because of the bug it causes - KT-61039 We just accepted that we will have one more "green in K1 -> red in K2" case --- .../org/jetbrains/kotlin/resolve/OverrideResolver.kt | 10 ++++++---- .../changeModalityFromAbstractToFinalInOverride.kt | 2 +- .../changeModalityFromAbstractToOpenInOverride.fir.kt | 2 +- .../changeModalityFromAbstractToOpenInOverride.kt | 4 ++-- .../multiplatform/expectObjectWithAbstractMember.kt | 2 +- .../dontOverrideMethodsFromInterfaceInCommonCode.kt | 4 ++-- .../extendExpectedClassWithAbstractMember.kt | 8 ++++---- ...tendExpectedClassWithoutExplicitOverrideOfMethod.kt | 2 +- .../org/jetbrains/kotlin/resolve/DescriptorUtils.java | 4 ++++ 9 files changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt index f1357d46785..34c56540668 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverrideResolver.kt @@ -36,7 +36,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.platform.PlatformSpecificDiagnosticComponents import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractDeclaration +import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractFakeOverride import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE import org.jetbrains.kotlin.resolve.calls.util.isOrOverridesSynthesized import org.jetbrains.kotlin.types.* @@ -132,7 +132,7 @@ class OverrideResolver( this(delegateStrategy.klass, delegateStrategy.classDescriptor) override fun doReportErrors() { - val canHaveAbstractMembers = classCanHaveAbstractDeclaration(classDescriptor) + val canHaveAbstractMembers = classCanHaveAbstractFakeOverride(classDescriptor) if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) { if (languageVersionSettings.supportsFeature(AbstractClassMemberNotImplementedWithIntermediateAbstractClass)) { trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first())) @@ -260,7 +260,7 @@ class OverrideResolver( } open fun doReportErrors() { - val canHaveAbstractMembers = classCanHaveAbstractDeclaration(classDescriptor) + val canHaveAbstractMembers = classCanHaveAbstractFakeOverride(classDescriptor) if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) { trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first())) } else if (abstractNoImpl.isNotEmpty() && !canHaveAbstractMembers) { @@ -708,9 +708,11 @@ class OverrideResolver( for (overridden in relevantDirectlyOverridden) { val containingDeclaration = overridden.containingDeclaration as? ClassDescriptor ?: continue if (containingDeclaration.kind == ClassKind.CLASS) { - if (overridden.kind == FAKE_OVERRIDE) { + if (overridden.kind == FAKE_OVERRIDE && !containingDeclaration.isExpect) { // Fake override in a class in fact can mean an interface member // We will process it at the end + // Note: with expect containing class, the situation is unclear, so we miss this case + // See extendExpectedClassWithAbstractMember.kt (BaseA, BaseAImpl, DerivedA1) fakeOverrideInBaseClass = overridden } overridesClassMember = true diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.kt index 501f12e7aab..d73e7b50807 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToFinalInOverride.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/changeModalityFromAbstractToOpenInOverride.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.fir.kt index e8ad965bf7c..61de83ab2f0 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.fir.kt @@ -11,7 +11,7 @@ interface Base { // 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`. -// Luckily, we report ABSTRACT_MEMBER_NOT_IMPLEMENTED additionally. +// https://youtrack.jetbrains.com/issue/KT-59739 actual open class Foo : Base { override fun foo() {} } diff --git a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.kt b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.kt index d8411563f22..8af6b6eb340 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/actualClassifierMustHasTheSameMembersAsNonFinalExpectClassifierChecker/changeModalityFromAbstractToOpenInOverride.kt @@ -3,7 +3,7 @@ interface Base { fun foo() } -expect open class Foo() : Base +expect open class Foo() : Base // MODULE: m2-jvm()()(m1-common) @@ -11,7 +11,7 @@ expect open object Implementation : Base +expect object Implementation : Base // MODULE: m1-jvm()()(m1-common) // FILE: jvm.kt diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt index c467cc786c1..70978a22306 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/dontOverrideMethodsFromInterfaceInCommonCode.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/extendExpectedClassWithAbstractMember.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.kt index 1c39701147c..b2fb328389c 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithAbstractMember.kt @@ -4,9 +4,9 @@ expect abstract class BaseA() { abstract fun foo() } -expect open class BaseAImpl() : BaseA +expect open class BaseAImpl() : BaseA -class DerivedA1 : BaseAImpl() +class DerivedA1 : BaseAImpl() class DerivedA2 : BaseAImpl() { override fun foo() = super.foo() } @@ -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.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.kt index 87275fb43f3..e49d1b61c91 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/extendExpectedClassWithoutExplicitOverrideOfMethod.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/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java index e4d743eaad1..a7b25398cd2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorUtils.java @@ -505,6 +505,10 @@ public class DescriptorUtils { UnsignedTypes.INSTANCE.isUnsignedType(type); } + public static boolean classCanHaveAbstractFakeOverride(@NotNull ClassDescriptor classDescriptor) { + return classCanHaveAbstractDeclaration(classDescriptor) || classDescriptor.isExpect(); + } + public static boolean classCanHaveAbstractDeclaration(@NotNull ClassDescriptor classDescriptor) { return classDescriptor.getModality() == Modality.ABSTRACT || isSealedClass(classDescriptor)