From 4c88e2a0bcf39d4c62152fb9c682b581a947fe43 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 18 Feb 2016 17:59:42 +0300 Subject: [PATCH] Use original descriptor when mapping fake override Otherwise wrong CONFLICTING_INHERITED_JVM_DECLARATIONS were reported #KT-10691 Fixed --- ...FactoryForDuplicateSignatureDiagnostics.kt | 25 ++++++++--- .../differentErasureInSuperClass.kt | 15 +++++++ .../differentErasureInSuperClassComplex.kt | 35 ++++++++++++++++ .../clashFromInterfaceAndSuperClass.kt | 19 +++++++++ .../clashFromInterfaceAndSuperClass.txt | 42 +++++++++++++++++++ .../overridesBuiltinNoMagic.kt | 5 ++- .../overridesBuiltinNoMagic.txt | 32 ++++++++++++++ .../diagnostics/tests/override/Generics.kt | 8 ++-- .../checkers/DiagnosticsTestGenerated.java | 6 +++ .../BlackBoxCodegenTestGenerated.java | 12 ++++++ .../test/semantics/BridgeTestGenerated.java | 12 ++++++ 11 files changed, 200 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt create mode 100644 compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClassComplex.kt create mode 100644 compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.kt create mode 100644 compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt index 9d147e0c81b..af844115f29 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/BuilderFactoryForDuplicateSignatureDiagnostics.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.load.java.descriptors.getParentJavaStaticClassScope import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor import org.jetbrains.kotlin.resolve.jvm.diagnostics.* import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.utils.addIfNotNull @@ -154,20 +155,27 @@ class BuilderFactoryForDuplicateSignatureDiagnostics( val groupedBySignature = MultiMap.create() fun processMember(member: DeclarationDescriptor?) { + if (member !is CallableMemberDescriptor) return // a member of super is not visible: no override - if (member is DeclarationDescriptorWithVisibility && member.visibility == Visibilities.INVISIBLE_FAKE) return + if (member.visibility == Visibilities.INVISIBLE_FAKE) return // if a signature clashes with a SAM-adapter or something like that, there's no harm - if (member is CallableMemberDescriptor && isOrOverridesSamAdapter(member)) return + if (isOrOverridesSamAdapter(member)) return if (member is PropertyDescriptor) { processMember(member.getter) processMember(member.setter) } else if (member is FunctionDescriptor) { - val methodSignature = typeMapper.mapSignature(member) - val rawSignature = RawSignature( - methodSignature.asmMethod.name!!, methodSignature.asmMethod.descriptor!!, MemberKind.METHOD) - groupedBySignature.putValue(rawSignature, OtherOrigin(member)) + val signatures = + if (member.kind == FAKE_OVERRIDE) + member.overriddenDescriptors.mapTo(HashSet()) { it.original.asRawSignature() } + else + setOf(member.asRawSignature()) + + signatures.forEach { + rawSignature -> + groupedBySignature.putValue(rawSignature, OtherOrigin(member)) + } } } @@ -183,6 +191,11 @@ class BuilderFactoryForDuplicateSignatureDiagnostics( return groupedBySignature } + private fun FunctionDescriptor.asRawSignature() = + with(typeMapper.mapSignature(this)) { + RawSignature(asmMethod.name!!, asmMethod.descriptor!!, MemberKind.METHOD) + } + private fun isOrOverridesSamAdapter(descriptor: CallableMemberDescriptor): Boolean { if (descriptor is SamAdapterDescriptor<*>) return true diff --git a/compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt b/compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt new file mode 100644 index 00000000000..d3bb7ce59e7 --- /dev/null +++ b/compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt @@ -0,0 +1,15 @@ +public open class A { + fun foo(x: T) = "O" + fun foo(x: A) = "K" +} + +// Shoudt not be reported CONFLICTING_INHERITED_JVM_DECLARATIONS +class B : A>() + +fun box(): String { + val x: A = A() + val y: A> = A() + val b = B() + + return b.foo(x) + b.foo(y) +} diff --git a/compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClassComplex.kt b/compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClassComplex.kt new file mode 100644 index 00000000000..473cee266e1 --- /dev/null +++ b/compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClassComplex.kt @@ -0,0 +1,35 @@ +public open class A { + fun foo(x: T) = "O" + fun foo(x: A) = "K" +} + +interface C { + fun foo(x: E): String + fun foo(x: A): String +} + +interface D { + fun foo(x: A>): String +} + +// Shoudt not be reported CONFLICTING_INHERITED_JVM_DECLARATIONS +class B : A>(), C>, D + +fun box(): String { + val x: A = A() + val y: A> = A() + + val b = B() + val bResult = b.foo(x) + b.foo(y) + if (bResult != "OK") return "fail 1: $bResult" + + val c: C> = B() + val cResult = c.foo(x) + c.foo(y) + if (cResult != "OK") return "fail 2: $cResult" + + val d: D = B() + + if (d.foo(y) != "K") return "fail 3" + + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.kt new file mode 100644 index 00000000000..369943f3553 --- /dev/null +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +public open class A { + fun foo(x: T) = "O" + fun foo(x: A) = "K" +} + +interface C { + fun foo(x: E): String + fun foo(x: A): String +} + +interface D { + fun foo(x: A): String +} + +class B1 : A>(), D + +interface B2 : C>, D diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.txt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.txt new file mode 100644 index 00000000000..64017b281bd --- /dev/null +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.txt @@ -0,0 +1,42 @@ +package + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(/*0*/ x: A): kotlin.String + public final fun foo(/*0*/ x: T): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B1 : A>, D { + public constructor B1() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun foo(/*0*/ x: A>): kotlin.String + public final override /*2*/ /*fake_override*/ fun foo(/*0*/ x: A): kotlin.String + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface B2 : C>, D { + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ x: A>): kotlin.String + public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ x: A): kotlin.String + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface C { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(/*0*/ x: A): kotlin.String + public abstract fun foo(/*0*/ x: E): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface D { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(/*0*/ x: A): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt index e81f71dd00d..e1f345eb934 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.kt @@ -143,7 +143,10 @@ public class X implements java.util.List { // FILE: main.kt -class Y : X() +class Y : X() +class Y2 : X() { + override fun removeAt(index: Int) = "" +} fun main() { X().remove("") diff --git a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt index 2111dfe2c76..de205f9591f 100644 --- a/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt +++ b/compiler/testData/diagnostics/tests/j+k/collectionOverrides/overridesBuiltinNoMagic.txt @@ -65,3 +65,35 @@ public final class Y : X { @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun toArray(/*0*/ a: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!> public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +public final class Y2 : X { + public constructor Y2() + public open override /*1*/ /*fake_override*/ val size: kotlin.Int + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun add(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.String!): kotlin.Unit + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun add(/*0*/ element: kotlin.String!): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ index: kotlin.Int, /*1*/ elements: kotlin.collections.Collection): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ elements: kotlin.collections.Collection): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun clear(): kotlin.Unit + @java.lang.Override() public open override /*1*/ /*fake_override*/ /*isHiddenToOvercomeSignatureClash*/ fun contains(/*0*/ o: kotlin.String!): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun contains(/*0*/ element: kotlin.String!): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun containsAll(/*0*/ elements: kotlin.collections.Collection): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun get(/*0*/ index: kotlin.Int): kotlin.String! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun indexOf(/*0*/ o: kotlin.String!): kotlin.Int + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean + @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun iterator(): kotlin.collections.MutableIterator + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun lastIndexOf(/*0*/ o: kotlin.String!): kotlin.Int + @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun listIterator(): kotlin.collections.MutableListIterator + @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.collections.MutableListIterator + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun remove(/*0*/ o: kotlin.String!): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun removeAll(/*0*/ elements: kotlin.collections.Collection): kotlin.Boolean + public open override /*1*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.String + @java.lang.Override() public open override /*1*/ /*fake_override*/ /*isHiddenToOvercomeSignatureClash*/ fun removeAt(/*0*/ index: kotlin.Int): kotlin.String! + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun retainAll(/*0*/ elements: kotlin.collections.Collection): kotlin.Boolean + @java.lang.Override() public open override /*1*/ /*fake_override*/ fun set(/*0*/ index: kotlin.Int, /*1*/ element: kotlin.String!): kotlin.String! + @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun subList(/*0*/ fromIndex: kotlin.Int, /*1*/ toIndex: kotlin.Int): kotlin.collections.MutableList + @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun toArray(): kotlin.Array<(out) kotlin.Any!> + @org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun toArray(/*0*/ a: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!> + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/override/Generics.kt b/compiler/testData/diagnostics/tests/override/Generics.kt index 8d83081ba5d..66436675fa8 100644 --- a/compiler/testData/diagnostics/tests/override/Generics.kt +++ b/compiler/testData/diagnostics/tests/override/Generics.kt @@ -49,12 +49,12 @@ abstract class MyAbstractClass1 : MyTrait, MyAbstractClass() { abstract class MyLegalAbstractClass1 : MyTrait, MyAbstractClass() {} class MyIllegalClass2(t : T) : MyTrait, MyAbstractClass() { - fun foo(t: T) = t - fun bar(t: T) = t + fun foo(t: T) = t + fun bar(t: T) = t val <R> pr : T = t } abstract class MyLegalAbstractClass2(t : T) : MyTrait, MyAbstractClass() { - fun foo(t: T) = t - fun bar(t: T) = t + fun foo(t: T) = t + fun bar(t: T) = t val <R> pr : T = t } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index faae6800644..7dd52e6d963 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -5333,6 +5333,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("clashFromInterfaceAndSuperClass.kt") + public void testClashFromInterfaceAndSuperClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.kt"); + doTest(fileName); + } + @TestMetadata("collections.kt") public void testCollections() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/collections.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index b90e4b2aaa4..283fbc0d047 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -690,6 +690,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("differentErasureInSuperClass.kt") + public void testDifferentErasureInSuperClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt"); + doTest(fileName); + } + + @TestMetadata("differentErasureInSuperClassComplex.kt") + public void testDifferentErasureInSuperClassComplex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClassComplex.kt"); + doTest(fileName); + } + @TestMetadata("enum.kt") public void testEnum() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/substitutionInSuperClass/enum.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BridgeTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BridgeTestGenerated.java index 35819d24c9f..faa21246424 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BridgeTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BridgeTestGenerated.java @@ -319,6 +319,18 @@ public class BridgeTestGenerated extends AbstractBridgeTest { doTest(fileName); } + @TestMetadata("differentErasureInSuperClass.kt") + public void testDifferentErasureInSuperClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClass.kt"); + doTest(fileName); + } + + @TestMetadata("differentErasureInSuperClassComplex.kt") + public void testDifferentErasureInSuperClassComplex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/substitutionInSuperClass/differentErasureInSuperClassComplex.kt"); + doTest(fileName); + } + @TestMetadata("enum.kt") public void testEnum() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/substitutionInSuperClass/enum.kt");