Do not generate mutable collection stub methods in interfaces

#KT-12359 Fixed
This commit is contained in:
Denis Zharkov
2016-06-24 16:37:07 +03:00
parent 1780f57265
commit 2578fc3344
6 changed files with 22 additions and 26 deletions
@@ -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
@@ -0,0 +1,2 @@
interface A<E> : Collection<E>
interface B<E> : List<E>
@@ -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 {