diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt index a7ccbe3b33d..cff39967a37 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt @@ -61,7 +61,8 @@ object BuiltinSpecialBridgesUtil { // e.g. `size()I` val overriddenBuiltinSignature = signatureByDescriptor(overriddenBuiltin) - val needGenerateSpecialBridge = needGenerateSpecialBridge(function, reachableDeclarations, overriddenBuiltin) + val needGenerateSpecialBridge = needGenerateSpecialBridge( + function, reachableDeclarations, overriddenBuiltin, signatureByDescriptor, overriddenBuiltinSignature) && methodItself != overriddenBuiltinSignature val specialBridge = if (needGenerateSpecialBridge) @@ -107,15 +108,21 @@ private fun findSuperImplementationForStubDelegation(function: FunctionDescripto private fun findAllReachableDeclarations(functionDescriptor: FunctionDescriptor): MutableSet = findAllReachableDeclarations(DescriptorBasedFunctionHandle(functionDescriptor)).map { it.descriptor }.toMutableSet() -private fun needGenerateSpecialBridge( +private fun needGenerateSpecialBridge( functionDescriptor: FunctionDescriptor, reachableDeclarations: Collection, - specialCallableDescriptor: CallableMemberDescriptor + specialCallableDescriptor: CallableMemberDescriptor, + signatureByDescriptor: (FunctionDescriptor) -> Signature, + overriddenBuiltinSignature: Signature ): Boolean { val classDescriptor = functionDescriptor.containingDeclaration as ClassDescriptor return !classDescriptor.hasRealKotlinSuperClassWithOverrideOf(specialCallableDescriptor) && specialCallableDescriptor.modality != Modality.FINAL - && reachableDeclarations.none { it.containingDeclaration is JavaClassDescriptor && it.modality == Modality.FINAL } + && reachableDeclarations.none { + it.containingDeclaration is JavaClassDescriptor + && it.modality == Modality.FINAL + && signatureByDescriptor(it) == overriddenBuiltinSignature + } } public fun isValueArgumentForCallToMethodWithTypeCheckBarrier( diff --git a/compiler/testData/codegen/box/builtinsProperties/irrelevantRemoveAtOverride.kt b/compiler/testData/codegen/box/builtinsProperties/irrelevantRemoveAtOverride.kt new file mode 100644 index 00000000000..0e385c6fc30 --- /dev/null +++ b/compiler/testData/codegen/box/builtinsProperties/irrelevantRemoveAtOverride.kt @@ -0,0 +1,104 @@ +interface Container { + fun removeAt(x: Int): String +} + +open class ContainerImpl : Container { + override fun removeAt(x: Int) = "abc" +} + +class A : ContainerImpl(), MutableList { + override fun isEmpty(): Boolean { + throw UnsupportedOperationException() + } + + override val size: Int + get() = throw UnsupportedOperationException() + + override fun contains(element: String): Boolean { + throw UnsupportedOperationException() + } + + override fun containsAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun get(index: Int): String { + throw UnsupportedOperationException() + } + + override fun indexOf(element: String): Int { + throw UnsupportedOperationException() + } + + override fun lastIndexOf(element: String): Int { + throw UnsupportedOperationException() + } + + override fun add(element: String): Boolean { + throw UnsupportedOperationException() + } + + override fun remove(element: String): Boolean { + throw UnsupportedOperationException() + } + + override fun addAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun addAll(index: Int, elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun removeAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun retainAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun clear() { + throw UnsupportedOperationException() + } + + override fun set(index: Int, element: String): String { + throw UnsupportedOperationException() + } + + override fun add(index: Int, element: String) { + throw UnsupportedOperationException() + } + + override fun listIterator(): MutableListIterator { + throw UnsupportedOperationException() + } + + override fun listIterator(index: Int): MutableListIterator { + throw UnsupportedOperationException() + } + + override fun subList(fromIndex: Int, toIndex: Int): MutableList { + throw UnsupportedOperationException() + } + + override fun iterator(): MutableIterator { + throw UnsupportedOperationException() + } +} + +fun box(): String { + val a = A() + if (a.removeAt(0) != "abc") return "fail 1" + + val l: MutableList = a + if (l.removeAt(0) != "abc") return "fail 2" + + val anyList: MutableList = a as MutableList + if (anyList.removeAt(0) != "abc") return "fail 3" + + val container: Container = a + if (container.removeAt(0) != "abc") return "fail 4" + + return "OK" +} diff --git a/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/J.java b/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/J.java new file mode 100644 index 00000000000..54a7984f212 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/J.java @@ -0,0 +1,5 @@ +import java.util.*; + +public class J implements Container { + final public String removeAt(int index) { return "abc"; } +} diff --git a/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/irrelevantRemoveAtOverrideInJava.kt b/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/irrelevantRemoveAtOverrideInJava.kt new file mode 100644 index 00000000000..0b473335efa --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/irrelevantRemoveAtOverrideInJava.kt @@ -0,0 +1,100 @@ +interface Container { + fun removeAt(x: Int): String +} + +class A : J(), MutableList { + override fun isEmpty(): Boolean { + throw UnsupportedOperationException() + } + + override val size: Int + get() = throw UnsupportedOperationException() + + override fun contains(element: String): Boolean { + throw UnsupportedOperationException() + } + + override fun containsAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun get(index: Int): String { + throw UnsupportedOperationException() + } + + override fun indexOf(element: String): Int { + throw UnsupportedOperationException() + } + + override fun lastIndexOf(element: String): Int { + throw UnsupportedOperationException() + } + + override fun add(element: String): Boolean { + throw UnsupportedOperationException() + } + + override fun remove(element: String): Boolean { + throw UnsupportedOperationException() + } + + override fun addAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun addAll(index: Int, elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun removeAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun retainAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } + + override fun clear() { + throw UnsupportedOperationException() + } + + override fun set(index: Int, element: String): String { + throw UnsupportedOperationException() + } + + override fun add(index: Int, element: String) { + throw UnsupportedOperationException() + } + + override fun listIterator(): MutableListIterator { + throw UnsupportedOperationException() + } + + override fun listIterator(index: Int): MutableListIterator { + throw UnsupportedOperationException() + } + + override fun subList(fromIndex: Int, toIndex: Int): MutableList { + throw UnsupportedOperationException() + } + + override fun iterator(): MutableIterator { + throw UnsupportedOperationException() + } +} + +fun box(): String { + val a = A() + if (a.removeAt(0) != "abc") return "fail 1" + + val l: MutableList = a + if (l.removeAt(0) != "abc") return "fail 2" + + val anyList: MutableList = a as MutableList + if (anyList.removeAt(0) != "abc") return "fail 3" + + val container: Container = a + if (container.removeAt(0) != "abc") return "fail 4" + + return "OK" +} diff --git a/compiler/testData/codegen/boxWithJava/collections/irrelevantSizeOverrideInJava/J.java b/compiler/testData/codegen/boxWithJava/collections/irrelevantSizeOverrideInJava/J.java new file mode 100644 index 00000000000..891235751f4 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/collections/irrelevantSizeOverrideInJava/J.java @@ -0,0 +1,5 @@ +import java.util.*; + +public class J implements Sized { + final public int getSize() { return 123; } +} diff --git a/compiler/testData/codegen/boxWithJava/collections/irrelevantSizeOverrideInJava/irrelevantSizeOverrideInJava.kt b/compiler/testData/codegen/boxWithJava/collections/irrelevantSizeOverrideInJava/irrelevantSizeOverrideInJava.kt new file mode 100644 index 00000000000..8e382956c79 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/collections/irrelevantSizeOverrideInJava/irrelevantSizeOverrideInJava.kt @@ -0,0 +1,34 @@ +interface Sized { + val size: Int +} + +class A : J(), Collection { + override fun isEmpty(): Boolean { + throw UnsupportedOperationException() + } + + override fun contains(element: T): Boolean { + throw UnsupportedOperationException() + } + + override fun iterator(): Iterator { + throw UnsupportedOperationException() + } + + override fun containsAll(elements: Collection): Boolean { + throw UnsupportedOperationException() + } +} + +fun box(): String { + val a = A() + if (a.size != 123) return "fail 1" + + val c: Collection = a + if (c.size != 123) return "fail 2" + + val sized: Sized = a + if (sized.size != 123) return "fail 3" + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 3c7f77d2d64..4cb7bc89229 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -922,6 +922,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("irrelevantRemoveAtOverride.kt") + public void testIrrelevantRemoveAtOverride() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinsProperties/irrelevantRemoveAtOverride.kt"); + doTest(fileName); + } + @TestMetadata("maps.kt") public void testMaps() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinsProperties/maps.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 18ade3404b4..2b708c093f6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -197,6 +197,18 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege doTestWithJava(fileName); } + @TestMetadata("irrelevantRemoveAtOverrideInJava") + public void testIrrelevantRemoveAtOverrideInJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/irrelevantRemoveAtOverrideInJava/"); + doTestWithJava(fileName); + } + + @TestMetadata("irrelevantSizeOverrideInJava") + public void testIrrelevantSizeOverrideInJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/irrelevantSizeOverrideInJava/"); + doTestWithJava(fileName); + } + @TestMetadata("mutableList") public void testMutableList() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/mutableList/");