KT-12358: fake override of a method of 'Any' in an interface is not an "implementation".
This commit is contained in:
@@ -32,6 +32,7 @@ import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ReadOnly;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactoryWithPsiElement;
|
||||
@@ -618,13 +619,40 @@ public class OverrideResolver {
|
||||
private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
|
||||
List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
|
||||
for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
|
||||
if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
|
||||
if (isImplementation(overriddenDescriptor)) {
|
||||
result.add(overriddenDescriptor);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isImplementation(@NotNull CallableMemberDescriptor callableMemberDescriptor) {
|
||||
// An abstract member is not an implementation.
|
||||
if (callableMemberDescriptor.getModality() == Modality.ABSTRACT) return false;
|
||||
|
||||
// Interfaces contain fake overrides for 'toString', 'hashCode', 'equals'.
|
||||
// They are not considered implementations if their dispatch receiver type is 'Any'.
|
||||
DeclarationDescriptor containingDeclaration = callableMemberDescriptor.getContainingDeclaration();
|
||||
assert containingDeclaration instanceof ClassDescriptor :
|
||||
"ClassDescriptor expected, got " + containingDeclaration + " for " + callableMemberDescriptor;
|
||||
ClassDescriptor containingClassDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
if (containingClassDescriptor.getKind() == ClassKind.INTERFACE && callableMemberDescriptor.getKind() == FAKE_OVERRIDE) {
|
||||
ReceiverParameterDescriptor dispatchReceiverParameter = callableMemberDescriptor.getDispatchReceiverParameter();
|
||||
if (dispatchReceiverParameter == null) return false;
|
||||
if (KotlinBuiltIns.isAny(dispatchReceiverParameter.getType())) return false;
|
||||
}
|
||||
|
||||
// A FAKE_OVERRIDE is an implementation iff it overrides an implementation.
|
||||
if (callableMemberDescriptor.getKind() == FAKE_OVERRIDE) {
|
||||
for (CallableMemberDescriptor overriddenDescriptor : callableMemberDescriptor.getOverriddenDescriptors()) {
|
||||
if (isImplementation(overriddenDescriptor)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void filterNotSynthesizedDescriptorsByModality(
|
||||
@NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
|
||||
@NotNull List<CallableMemberDescriptor> abstractOverridden,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
abstract class A {
|
||||
abstract override fun toString(): String
|
||||
}
|
||||
|
||||
interface B
|
||||
|
||||
abstract class C : A(), B
|
||||
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Test<!> : C()
|
||||
@@ -0,0 +1,28 @@
|
||||
package
|
||||
|
||||
public abstract class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract override /*1*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public abstract class C : A, B {
|
||||
public constructor C()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Test : C {
|
||||
public constructor Test()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -12216,6 +12216,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt12358.kt")
|
||||
public void testKt12358() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/kt12358.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt1862.kt")
|
||||
public void testKt1862() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/kt1862.kt");
|
||||
|
||||
Reference in New Issue
Block a user