Use original descriptor when mapping fake override
Otherwise wrong CONFLICTING_INHERITED_JVM_DECLARATIONS were reported #KT-10691 Fixed
This commit is contained in:
+19
-6
@@ -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<RawSignature, JvmDeclarationOrigin>()
|
||||
|
||||
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
|
||||
|
||||
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
public open class A<T> {
|
||||
fun foo(x: T) = "O"
|
||||
fun foo(x: A<T>) = "K"
|
||||
}
|
||||
|
||||
// Shoudt not be reported CONFLICTING_INHERITED_JVM_DECLARATIONS
|
||||
class B : A<A<String>>()
|
||||
|
||||
fun box(): String {
|
||||
val x: A<String> = A()
|
||||
val y: A<A<String>> = A()
|
||||
val b = B()
|
||||
|
||||
return b.foo(x) + b.foo(y)
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
public open class A<T> {
|
||||
fun foo(x: T) = "O"
|
||||
fun foo(x: A<T>) = "K"
|
||||
}
|
||||
|
||||
interface C<E> {
|
||||
fun foo(x: E): String
|
||||
fun foo(x: A<E>): String
|
||||
}
|
||||
|
||||
interface D {
|
||||
fun foo(x: A<A<String>>): String
|
||||
}
|
||||
|
||||
// Shoudt not be reported CONFLICTING_INHERITED_JVM_DECLARATIONS
|
||||
class B : A<A<String>>(), C<A<String>>, D
|
||||
|
||||
fun box(): String {
|
||||
val x: A<String> = A()
|
||||
val y: A<A<String>> = A()
|
||||
|
||||
val b = B()
|
||||
val bResult = b.foo(x) + b.foo(y)
|
||||
if (bResult != "OK") return "fail 1: $bResult"
|
||||
|
||||
val c: C<A<String>> = 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"
|
||||
}
|
||||
compiler/testData/diagnostics/tests/duplicateJvmSignature/erasure/clashFromInterfaceAndSuperClass.kt
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
public open class A<T> {
|
||||
fun foo(x: T) = "O"
|
||||
fun foo(x: A<T>) = "K"
|
||||
}
|
||||
|
||||
interface C<E> {
|
||||
fun foo(x: E): String
|
||||
fun foo(x: A<E>): String
|
||||
}
|
||||
|
||||
interface D {
|
||||
fun foo(x: A<String>): String
|
||||
}
|
||||
|
||||
class <!CONFLICTING_INHERITED_JVM_DECLARATIONS!>B1<!> : A<A<String>>(), D
|
||||
|
||||
interface <!CONFLICTING_INHERITED_JVM_DECLARATIONS!>B2<!> : C<A<String>>, D
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package
|
||||
|
||||
public open class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(/*0*/ x: A<T>): 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<A<kotlin.String>>, 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<A<kotlin.String>>): kotlin.String
|
||||
public final override /*2*/ /*fake_override*/ fun foo(/*0*/ x: A<kotlin.String>): 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<A<kotlin.String>>, 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<A<kotlin.String>>): kotlin.String
|
||||
public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ x: A<kotlin.String>): 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</*0*/ E> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(/*0*/ x: A<E>): 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>): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+4
-1
@@ -143,7 +143,10 @@ public class X implements java.util.List<String> {
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
class <!CONFLICTING_INHERITED_JVM_DECLARATIONS, CONFLICTING_INHERITED_JVM_DECLARATIONS!>Y<!> : X()
|
||||
class Y : X()
|
||||
class <!CONFLICTING_JVM_DECLARATIONS!>Y2<!> : X() {
|
||||
<!CONFLICTING_JVM_DECLARATIONS!>override fun removeAt(index: Int)<!> = ""
|
||||
}
|
||||
|
||||
fun main() {
|
||||
X().remove("")
|
||||
|
||||
+32
@@ -65,3 +65,35 @@ public final class Y : X {
|
||||
@org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun </*0*/ T : kotlin.Any!> 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.String!>): kotlin.Boolean
|
||||
@java.lang.Override() public open override /*1*/ /*fake_override*/ fun addAll(/*0*/ elements: kotlin.collections.Collection<kotlin.String!>): 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.String!>): 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<kotlin.String!>
|
||||
@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<kotlin.String!>
|
||||
@org.jetbrains.annotations.NotNull() @java.lang.Override() public open override /*1*/ /*fake_override*/ fun listIterator(/*0*/ index: kotlin.Int): kotlin.collections.MutableListIterator<kotlin.String!>
|
||||
@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.String!>): 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.String!>): 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<kotlin.String!>
|
||||
@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 </*0*/ T : kotlin.Any!> toArray(/*0*/ a: kotlin.Array<(out) T!>!): kotlin.Array<(out) T!>
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@@ -49,12 +49,12 @@ abstract class MyAbstractClass1 : MyTrait<Int>, MyAbstractClass<String>() {
|
||||
abstract class MyLegalAbstractClass1 : MyTrait<Int>, MyAbstractClass<String>() {}
|
||||
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass2<!><T>(t : T) : MyTrait<Int>, MyAbstractClass<Int>() {
|
||||
fun foo(t: T) = t
|
||||
fun bar(t: T) = t
|
||||
<!ACCIDENTAL_OVERRIDE!>fun foo(t: T)<!> = t
|
||||
<!ACCIDENTAL_OVERRIDE!>fun bar(t: T)<!> = t
|
||||
<!CONFLICTING_OVERLOADS!>val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>R<!>> pr : T<!> = t
|
||||
}
|
||||
abstract class MyLegalAbstractClass2<T>(t : T) : MyTrait<Int>, MyAbstractClass<Int>() {
|
||||
fun foo(t: T) = t
|
||||
fun bar(t: T) = t
|
||||
<!ACCIDENTAL_OVERRIDE!>fun foo(t: T)<!> = t
|
||||
<!ACCIDENTAL_OVERRIDE!>fun bar(t: T)<!> = t
|
||||
<!CONFLICTING_OVERLOADS!>val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>R<!>> pr : T<!> = t
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
+12
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user