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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.ReadOnly;
|
import org.jetbrains.annotations.ReadOnly;
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactoryWithPsiElement;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactoryWithPsiElement;
|
||||||
@@ -618,13 +619,40 @@ public class OverrideResolver {
|
|||||||
private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
|
private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
|
||||||
List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
|
List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
|
||||||
for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
|
for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
|
||||||
if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
|
if (isImplementation(overriddenDescriptor)) {
|
||||||
result.add(overriddenDescriptor);
|
result.add(overriddenDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
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(
|
private static void filterNotSynthesizedDescriptorsByModality(
|
||||||
@NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
|
@NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
|
||||||
@NotNull List<CallableMemberDescriptor> abstractOverridden,
|
@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);
|
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")
|
@TestMetadata("kt1862.kt")
|
||||||
public void testKt1862() throws Exception {
|
public void testKt1862() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/kt1862.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/kt1862.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user