diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt index 6f185305bba..d1611393e5b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt @@ -101,10 +101,6 @@ class CollectionStubMethodGenerator( // present in the bytecode (abstract) and we don't want a duplicate signature error if (method.findOverriddenFromDirectSuperClass(descriptor)?.kind == DECLARATION) continue - // Otherwise we can safely generate the stub with the substituted signature - val signature = method.signature() - methodStubsToGenerate.add(signature) - // If the substituted signature differs from the original one in MutableCollection, we should also generate a stub with // the original (erased) signature. It doesn't really matter if this is a bridge method delegating to the first stub or // a method with its own exception-throwing code, for simplicity we do the latter here. @@ -114,9 +110,8 @@ class CollectionStubMethodGenerator( // methods which need to be generated with the ACC_SYNTHETIC flag val overriddenMethod = method.findOverriddenFromDirectSuperClass(mutableClass)!! val originalSignature = overriddenMethod.original.signature() - var specialSignature: JvmMethodSignature? = null - if (overriddenMethod.isBuiltinWithSpecialDescriptorInJvm()) { + val commonSignature = if (overriddenMethod.isBuiltinWithSpecialDescriptorInJvm()) { // Stubs for remove(Ljava/lang/Object;)Z and remove(I) should not be synthetic // Otherwise Javac will not see it val overriddenMethodSignature = overriddenMethod.signature() @@ -134,16 +129,19 @@ class CollectionStubMethodGenerator( else Pair(overriddenMethodSignature.asmMethod, overriddenMethodSignature.valueParameters) - specialSignature = JvmMethodGenericSignature( + JvmMethodGenericSignature( asmMethod, valueParameters, specialGenericSignature ) - - methodStubsToGenerate.add(specialSignature) + } + else { + method.signature() } - if (originalSignature.asmMethod != signature.asmMethod && originalSignature.asmMethod != specialSignature?.asmMethod) { + methodStubsToGenerate.add(commonSignature) + + if (originalSignature.asmMethod != commonSignature.asmMethod) { syntheticStubsToGenerate.add(originalSignature) } } diff --git a/compiler/testData/codegen/bytecodeListing/noRemoveAtInReadOnly.kt b/compiler/testData/codegen/bytecodeListing/noRemoveAtInReadOnly.kt new file mode 100644 index 00000000000..424e70e2710 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/noRemoveAtInReadOnly.kt @@ -0,0 +1,2 @@ +abstract class A : List +abstract class B : List diff --git a/compiler/testData/codegen/bytecodeListing/noRemoveAtInReadOnly.txt b/compiler/testData/codegen/bytecodeListing/noRemoveAtInReadOnly.txt new file mode 100644 index 00000000000..2345607eafa --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/noRemoveAtInReadOnly.txt @@ -0,0 +1,56 @@ +@kotlin.Metadata +public abstract class A { + public method (): void + public method add(p0: int, p1: java.lang.Object): void + public method add(p0: java.lang.Object): boolean + public method addAll(p0: int, p1: java.util.Collection): boolean + public method addAll(p0: java.util.Collection): boolean + public method clear(): void + public abstract method contains(p0: java.lang.Object): boolean + public abstract method getSize(): int + public abstract method indexOf(p0: java.lang.Object): int + public abstract method lastIndexOf(p0: java.lang.Object): int + public method listIterator(): java.util.ListIterator + public method listIterator(p0: int): java.util.ListIterator + public method remove(p0: int): java.lang.Object + public method remove(p0: java.lang.Object): boolean + public method removeAll(p0: java.util.Collection): boolean + public method retainAll(p0: java.util.Collection): boolean + public method set(p0: int, p1: java.lang.Object): java.lang.Object + public final method size(): int + public method subList(p0: int, p1: int): java.util.List + public method toArray(): java.lang.Object[] + public method toArray(p0: java.lang.Object[]): java.lang.Object[] +} + +@kotlin.Metadata +public abstract class B { + public method (): void + public method add(p0: int): boolean + public method add(p0: int, p1: int): void + public synthetic method add(p0: int, p1: java.lang.Object): void + public synthetic method add(p0: java.lang.Object): boolean + public method addAll(p0: int, p1: java.util.Collection): boolean + public method addAll(p0: java.util.Collection): boolean + public method clear(): void + public abstract method contains(p0: int): boolean + public final method contains(p0: java.lang.Object): boolean + public abstract method getSize(): int + public abstract method indexOf(p0: int): int + public final method indexOf(p0: java.lang.Object): int + public abstract method lastIndexOf(p0: int): int + public final method lastIndexOf(p0: java.lang.Object): int + public method listIterator(): java.util.ListIterator + public method listIterator(p0: int): java.util.ListIterator + public method remove(p0: int): int + public synthetic method remove(p0: int): java.lang.Object + public method remove(p0: java.lang.Object): boolean + public method removeAll(p0: java.util.Collection): boolean + public method retainAll(p0: java.util.Collection): boolean + public method set(p0: int, p1: int): java.lang.Integer + public synthetic method set(p0: int, p1: java.lang.Object): java.lang.Object + public final method size(): int + public method subList(p0: int, p1: int): java.util.List + public method toArray(): java.lang.Object[] + public method toArray(p0: java.lang.Object[]): java.lang.Object[] +} diff --git a/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.txt b/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.txt index 5bd65fc0c89..4deacf3dc41 100644 --- a/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.txt +++ b/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.txt @@ -18,7 +18,6 @@ public final class A2 { public method isEmpty(): boolean public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator public method remove(p0: java.lang.Object): boolean - public method remove(p0: java.lang.String): boolean public method removeAll(p0: java.util.Collection): boolean public method retainAll(p0: java.util.Collection): boolean public final method size(): int diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 93158279d8d..d844abbaf03 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -83,6 +83,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { doTest(fileName); } + @TestMetadata("noRemoveAtInReadOnly.kt") + public void testNoRemoveAtInReadOnly() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/noRemoveAtInReadOnly.kt"); + doTest(fileName); + } + @TestMetadata("samAdapterAndInlinedOne.kt") public void testSamAdapterAndInlinedOne() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt");