KT-12358: fake override of a method of 'Any' in an interface is not an "implementation".

This commit is contained in:
Dmitry Petrov
2016-05-19 15:49:00 +03:00
parent 74bddcfb70
commit b86fb64008
4 changed files with 72 additions and 1 deletions
@@ -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");