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 4f3ecedbca.
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
This commit is contained in:
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.platform.PlatformSpecificDiagnosticComponents
|
import org.jetbrains.kotlin.platform.PlatformSpecificDiagnosticComponents
|
||||||
import org.jetbrains.kotlin.psi.*
|
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.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.isOrOverridesSynthesized
|
import org.jetbrains.kotlin.resolve.calls.util.isOrOverridesSynthesized
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
@@ -132,7 +132,7 @@ class OverrideResolver(
|
|||||||
this(delegateStrategy.klass, delegateStrategy.classDescriptor)
|
this(delegateStrategy.klass, delegateStrategy.classDescriptor)
|
||||||
|
|
||||||
override fun doReportErrors() {
|
override fun doReportErrors() {
|
||||||
val canHaveAbstractMembers = classCanHaveAbstractDeclaration(classDescriptor)
|
val canHaveAbstractMembers = classCanHaveAbstractFakeOverride(classDescriptor)
|
||||||
if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
||||||
if (languageVersionSettings.supportsFeature(AbstractClassMemberNotImplementedWithIntermediateAbstractClass)) {
|
if (languageVersionSettings.supportsFeature(AbstractClassMemberNotImplementedWithIntermediateAbstractClass)) {
|
||||||
trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first()))
|
trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first()))
|
||||||
@@ -260,7 +260,7 @@ class OverrideResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun doReportErrors() {
|
open fun doReportErrors() {
|
||||||
val canHaveAbstractMembers = classCanHaveAbstractDeclaration(classDescriptor)
|
val canHaveAbstractMembers = classCanHaveAbstractFakeOverride(classDescriptor)
|
||||||
if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
if (abstractInBaseClassNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
||||||
trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first()))
|
trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.first()))
|
||||||
} else if (abstractNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
} else if (abstractNoImpl.isNotEmpty() && !canHaveAbstractMembers) {
|
||||||
@@ -708,9 +708,11 @@ class OverrideResolver(
|
|||||||
for (overridden in relevantDirectlyOverridden) {
|
for (overridden in relevantDirectlyOverridden) {
|
||||||
val containingDeclaration = overridden.containingDeclaration as? ClassDescriptor ?: continue
|
val containingDeclaration = overridden.containingDeclaration as? ClassDescriptor ?: continue
|
||||||
if (containingDeclaration.kind == ClassKind.CLASS) {
|
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
|
// Fake override in a class in fact can mean an interface member
|
||||||
// We will process it at the end
|
// 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
|
fakeOverrideInBaseClass = overridden
|
||||||
}
|
}
|
||||||
overridesClassMember = true
|
overridesClassMember = true
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ interface Base {
|
|||||||
fun foo()
|
fun foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
expect open <!ABSTRACT_MEMBER_NOT_IMPLEMENTED, ABSTRACT_MEMBER_NOT_IMPLEMENTED{JVM}!>class Foo<!> : Base
|
expect open class Foo : Base
|
||||||
|
|
||||||
// MODULE: m2-jvm()()(m1-common)
|
// MODULE: m2-jvm()()(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ interface Base {
|
|||||||
|
|
||||||
// Mismatched scope must be reported here. But it's false negative checker in K1.
|
// 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`.
|
// 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 {
|
actual open class Foo : Base {
|
||||||
override fun foo() {}
|
override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
interface Base {
|
interface Base {
|
||||||
fun foo()
|
fun foo()
|
||||||
}
|
}
|
||||||
expect open <!ABSTRACT_MEMBER_NOT_IMPLEMENTED, ABSTRACT_MEMBER_NOT_IMPLEMENTED{JVM}!>class Foo<!>() : Base
|
expect open class Foo() : Base
|
||||||
|
|
||||||
|
|
||||||
// MODULE: m2-jvm()()(m1-common)
|
// MODULE: m2-jvm()()(m1-common)
|
||||||
@@ -11,7 +11,7 @@ expect open <!ABSTRACT_MEMBER_NOT_IMPLEMENTED, ABSTRACT_MEMBER_NOT_IMPLEMENTED{J
|
|||||||
|
|
||||||
// Mismatched scope must be reported here. But it's false negative checker in K1.
|
// 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`.
|
// 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 {
|
actual open class Foo : Base {
|
||||||
override fun foo() {}
|
override fun foo() {}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ interface Base {
|
|||||||
fun foo()
|
fun foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
expect <!ABSTRACT_MEMBER_NOT_IMPLEMENTED, ABSTRACT_MEMBER_NOT_IMPLEMENTED{JVM}!>object Implementation<!> : Base
|
expect object Implementation : Base
|
||||||
|
|
||||||
// MODULE: m1-jvm()()(m1-common)
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|||||||
+2
-2
@@ -5,13 +5,13 @@ interface Foo {
|
|||||||
fun foo()
|
fun foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
expect <!ABSTRACT_MEMBER_NOT_IMPLEMENTED, ABSTRACT_MEMBER_NOT_IMPLEMENTED{JVM}!>class ImplicitFoo<!> : Foo
|
expect class ImplicitFoo : Foo
|
||||||
|
|
||||||
expect class ExplicitFoo : Foo {
|
expect class ExplicitFoo : Foo {
|
||||||
override fun foo()
|
override fun foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
expect <!ABSTRACT_MEMBER_NOT_IMPLEMENTED, ABSTRACT_MEMBER_NOT_IMPLEMENTED{JVM}!>class ImplicitFooCheck<!> : Foo
|
expect class ImplicitFooCheck : Foo
|
||||||
|
|
||||||
// MODULE: m2-jvm()()(m1-common)
|
// MODULE: m2-jvm()()(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|||||||
+4
-4
@@ -4,9 +4,9 @@
|
|||||||
expect abstract class BaseA() {
|
expect abstract class BaseA() {
|
||||||
abstract fun foo()
|
abstract fun foo()
|
||||||
}
|
}
|
||||||
expect open <!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class BaseAImpl<!>() : BaseA
|
expect open class BaseAImpl() : BaseA
|
||||||
|
|
||||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class DerivedA1<!> : BaseAImpl()
|
class DerivedA1 : BaseAImpl()
|
||||||
class DerivedA2 : BaseAImpl() {
|
class DerivedA2 : BaseAImpl() {
|
||||||
override fun foo() = super.foo()
|
override fun foo() = super.foo()
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ class DerivedA2 : BaseAImpl() {
|
|||||||
expect interface BaseB {
|
expect interface BaseB {
|
||||||
fun foo()
|
fun foo()
|
||||||
}
|
}
|
||||||
expect open <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class BaseBImpl<!>() : BaseB
|
expect open class BaseBImpl() : BaseB
|
||||||
|
|
||||||
class DerivedB1 : BaseBImpl()
|
class DerivedB1 : BaseBImpl()
|
||||||
class DerivedB2 : BaseBImpl() {
|
class DerivedB2 : BaseBImpl() {
|
||||||
@@ -58,7 +58,7 @@ sealed class BaseEImpl() : BaseE {
|
|||||||
expect interface BaseF {
|
expect interface BaseF {
|
||||||
fun foo()
|
fun foo()
|
||||||
}
|
}
|
||||||
expect <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class BaseFImpl<!>() : BaseF
|
expect class BaseFImpl() : BaseF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ expect abstract class Base {
|
|||||||
abstract fun foo()
|
abstract fun foo()
|
||||||
}
|
}
|
||||||
|
|
||||||
expect <!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED, ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED{JVM}!>class DerivedImplicit<!> : Base
|
expect class DerivedImplicit : Base
|
||||||
|
|
||||||
expect class DerivedExplicit : Base {
|
expect class DerivedExplicit : Base {
|
||||||
override fun foo()
|
override fun foo()
|
||||||
|
|||||||
@@ -505,6 +505,10 @@ public class DescriptorUtils {
|
|||||||
UnsignedTypes.INSTANCE.isUnsignedType(type);
|
UnsignedTypes.INSTANCE.isUnsignedType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean classCanHaveAbstractFakeOverride(@NotNull ClassDescriptor classDescriptor) {
|
||||||
|
return classCanHaveAbstractDeclaration(classDescriptor) || classDescriptor.isExpect();
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean classCanHaveAbstractDeclaration(@NotNull ClassDescriptor classDescriptor) {
|
public static boolean classCanHaveAbstractDeclaration(@NotNull ClassDescriptor classDescriptor) {
|
||||||
return classDescriptor.getModality() == Modality.ABSTRACT
|
return classDescriptor.getModality() == Modality.ABSTRACT
|
||||||
|| isSealedClass(classDescriptor)
|
|| isSealedClass(classDescriptor)
|
||||||
|
|||||||
Reference in New Issue
Block a user