Do not generate mutable collection stub methods in interfaces
#KT-12359 Fixed
This commit is contained in:
@@ -29,13 +29,15 @@ import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_SYNTHETIC
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import java.util.*
|
||||
|
||||
@@ -52,6 +54,7 @@ class CollectionStubMethodGenerator(
|
||||
private val typeMapper = state.typeMapper
|
||||
|
||||
fun generate() {
|
||||
if (descriptor.kind == ClassKind.INTERFACE) return
|
||||
val superCollectionClasses = findRelevantSuperCollectionClasses()
|
||||
if (superCollectionClasses.isEmpty()) return
|
||||
|
||||
@@ -281,19 +284,15 @@ class CollectionStubMethodGenerator(
|
||||
private fun FunctionDescriptor.signature(): JvmMethodGenericSignature = typeMapper.mapSignatureWithGeneric(this, OwnerKind.IMPLEMENTATION)
|
||||
|
||||
private fun generateMethodStub(signature: JvmMethodGenericSignature, synthetic: Boolean) {
|
||||
// TODO: investigate if it makes sense to generate abstract stubs in traits
|
||||
var access = ACC_PUBLIC
|
||||
if (descriptor.kind == ClassKind.INTERFACE) access = access or ACC_ABSTRACT
|
||||
if (synthetic) access = access or ACC_SYNTHETIC
|
||||
assert(descriptor.kind != ClassKind.INTERFACE) { "No stubs should be generated for interface ${descriptor.fqNameUnsafe}" }
|
||||
|
||||
val access = ACC_PUBLIC or (if (synthetic) ACC_SYNTHETIC else 0)
|
||||
val asmMethod = signature.asmMethod
|
||||
val genericSignature = if (synthetic) null else signature.genericsSignature
|
||||
val mv = v.newMethod(JvmDeclarationOrigin.NO_ORIGIN, access, asmMethod.name, asmMethod.descriptor, genericSignature, null)
|
||||
if (descriptor.kind != ClassKind.INTERFACE) {
|
||||
mv.visitCode()
|
||||
AsmUtil.genThrow(InstructionAdapter(mv), "java/lang/UnsupportedOperationException", "Mutating immutable collection")
|
||||
FunctionCodegen.endVisit(mv, "built-in stub for $signature", null)
|
||||
}
|
||||
mv.visitCode()
|
||||
AsmUtil.genThrow(InstructionAdapter(mv), "java/lang/UnsupportedOperationException", "Mutating immutable collection")
|
||||
FunctionCodegen.endVisit(mv, "built-in stub for $signature", null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
@kotlin.Metadata
|
||||
public interface ImmutableCollection {
|
||||
public abstract @org.jetbrains.annotations.NotNull method add(p0: java.lang.Object): ImmutableCollection
|
||||
public abstract method add(p0: java.lang.Object): boolean
|
||||
public abstract @org.jetbrains.annotations.NotNull method addAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): ImmutableCollection
|
||||
public abstract method addAll(p0: java.util.Collection): boolean
|
||||
public abstract method clear(): void
|
||||
public abstract method iterator(): java.util.Iterator
|
||||
public abstract @org.jetbrains.annotations.NotNull method remove(p0: java.lang.Object): ImmutableCollection
|
||||
public abstract method remove(p0: java.lang.Object): boolean
|
||||
public abstract method removeAll(p0: java.util.Collection): boolean
|
||||
public abstract method retainAll(p0: java.util.Collection): boolean
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
interface A<E> : Collection<E>
|
||||
interface B<E> : List<E>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
@kotlin.Metadata
|
||||
public interface A
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface B
|
||||
@@ -71,6 +71,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noCollectionStubMethodsInInterface.kt")
|
||||
public void testNoCollectionStubMethodsInInterface() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("samAdapterAndInlinedOne.kt")
|
||||
public void testSamAdapterAndInlinedOne() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt");
|
||||
|
||||
@@ -2079,16 +2079,7 @@ public final class kotlin/text/MatchGroup {
|
||||
}
|
||||
|
||||
public abstract interface class kotlin/text/MatchGroupCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public abstract synthetic fun add (Ljava/lang/Object;)Z
|
||||
public abstract fun add (Lkotlin/text/MatchGroup;)Z
|
||||
public abstract fun addAll (Ljava/util/Collection;)Z
|
||||
public abstract fun clear ()V
|
||||
public abstract fun get (I)Lkotlin/text/MatchGroup;
|
||||
public abstract fun iterator ()Ljava/util/Iterator;
|
||||
public abstract fun remove (Ljava/lang/Object;)Z
|
||||
public abstract fun remove (Lkotlin/text/MatchGroup;)Z
|
||||
public abstract fun removeAll (Ljava/util/Collection;)Z
|
||||
public abstract fun retainAll (Ljava/util/Collection;)Z
|
||||
}
|
||||
|
||||
public abstract interface class kotlin/text/MatchResult {
|
||||
|
||||
Reference in New Issue
Block a user