diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index 98012886a5d..6d6b3af5e33 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -155,6 +155,22 @@ abstract class Symbols(val context: T, private val val arrays = primitiveArrays.values + unsignedArrays.values + array + val collection = symbolTable.referenceClass(builtIns.collection) + val set = symbolTable.referenceClass(builtIns.set) + val list = symbolTable.referenceClass(builtIns.list) + val map = symbolTable.referenceClass(builtIns.map) + val mapEntry = symbolTable.referenceClass(builtIns.mapEntry) + val iterable = symbolTable.referenceClass(builtIns.iterable) + val listIterator = symbolTable.referenceClass(builtIns.listIterator) + val mutableCollection = symbolTable.referenceClass(builtIns.mutableCollection) + val mutableSet = symbolTable.referenceClass(builtIns.mutableSet) + val mutableList = symbolTable.referenceClass(builtIns.mutableList) + val mutableMap = symbolTable.referenceClass(builtIns.mutableMap) + val mutableMapEntry = symbolTable.referenceClass(builtIns.mutableMapEntry) + val mutableIterable = symbolTable.referenceClass(builtIns.mutableIterable) + val mutableIterator = symbolTable.referenceClass(builtIns.mutableIterator) + val mutableListIterator = symbolTable.referenceClass(builtIns.mutableListIterator) + abstract val copyRangeTo: Map abstract val coroutineImpl: IrClassSymbol diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt index 20cafbd60ae..813be6c5650 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/util/IrTypeUtils.kt @@ -119,3 +119,28 @@ fun IrType.substitute(substitutionMap: Map): IrTy newAnnotations ) } + +private fun getImmediateSupertypes(irClass: IrClass): List { + val originalSupertypes = irClass.superTypes + val args = irClass.defaultType.arguments.mapNotNull { (it as? IrTypeProjection)?.type } + return originalSupertypes + .filter { it.classOrNull != null } + .map { superType -> + superType.substitute(superType.classOrNull!!.owner.typeParameters, args) as IrSimpleType + } +} + +private fun collectAllSupertypes(irClass: IrClass, result: MutableSet) { + val immediateSupertypes = getImmediateSupertypes(irClass) + result.addAll(immediateSupertypes) + for (supertype in immediateSupertypes) { + supertype.classOrNull.let { collectAllSupertypes(it!!.owner, result) } + } +} + +fun getAllSupertypes(irClass: IrClass): MutableSet { + val result = HashSet() + + collectAllSupertypes(irClass, result) + return result +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 5b5d55c83c8..8cd80d679a6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -139,6 +139,7 @@ val jvmPhases = namedIrFilePhase( objectClassPhase then makeInitializersPhase(JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, true) then syntheticAccessorPhase then + collectionStubMethodLowering then bridgePhase then jvmOverloadsAnnotationPhase then jvmStaticAnnotationPhase then diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt index 6edbf246dc6..5642ba42fc4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt @@ -168,7 +168,7 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass addBridge( irClass, targetForCommonBridges, method, signaturesToSkip, defaultValueGenerator = null, - isSpecial = false + isSpecial = targetForCommonBridges.isCollectionStub() ) } } @@ -214,7 +214,7 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass isSpecial: Boolean, isSynthetic: Boolean ): IrSimpleFunction { - val modality = if (isSpecial) Modality.FINAL else Modality.OPEN + val modality = if (isSpecial && !target.isCollectionStub()) Modality.FINAL else Modality.OPEN val origin = if (isSynthetic) IrDeclarationOrigin.BRIDGE else IrDeclarationOrigin.BRIDGE_SPECIAL val visibility = if (signatureFunction.visibility === Visibilities.INTERNAL) Visibilities.PUBLIC else signatureFunction.visibility @@ -429,6 +429,9 @@ private data class SignatureWithSource(val signature: Method, val source: IrSimp fun IrSimpleFunction.overriddenInClasses(): Sequence = allOverridden().filter { !(it.parent.safeAs()?.isInterface ?: true) } +fun IrSimpleFunction.isCollectionStub(): Boolean = + origin == IrDeclarationOrigin.IR_BUILTINS_STUB + // TODO: At present, there is no reliable way to distinguish Java imports from Kotlin cross-module imports. val ORIGINS_FROM_JAVA = setOf(IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CollectionStubMethodLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CollectionStubMethodLowering.kt new file mode 100644 index 00000000000..025284ca243 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/CollectionStubMethodLowering.kt @@ -0,0 +1,212 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.ClassLoweringPass +import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irThrow +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.buildFun +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irString +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.FqName + +internal val collectionStubMethodLowering = makeIrFilePhase( + ::CollectionStubMethodLowering, + name = "CollectionStubMethod", + description = "Generate Collection stub methods" +) + +private class CollectionStubMethodLowering(val context: JvmBackendContext) : ClassLoweringPass { + + private val state = context.state + + private val typeMapper = state.typeMapper + + override fun lower(irClass: IrClass) { + if (irClass.isInterface) { + return + } + + val methodStubsToGenerate = generateRelevantStubMethods(irClass) + + // We don't need to generate stub for existing methods, but for FAKE_OVERRIDE methods with ABSTRACT modality, + // it means an abstract function in superclass that is not implemented yet, + // stub generation is still needed to avoid invocation error. + val existingMethodSignatures = irClass.functions.filterNot { + it.modality == Modality.ABSTRACT && it.origin == IrDeclarationOrigin.FAKE_OVERRIDE + }.associateBy { it.toSignature() } + + for (member in methodStubsToGenerate) { + val existingMethod = existingMethodSignatures[member.toSignature()] + if (existingMethod != null) { + // In the case that we find a defined method that matches the stub signature, we add the overridden symbols to that + // defined method, so that bridge lowering can still generate correct bridge for that method + existingMethod.overriddenSymbols.addAll(member.overriddenSymbols) + } else { + irClass.declarations.add(member) + } + } + } + + //TODO: replace with new typeMapper using no descriptor + private fun IrSimpleFunction.toSignature() = typeMapper.mapAsmMethod(this.descriptor).toString() + + private fun createStubMethod(function: IrSimpleFunction, irClass: IrClass, substitutionMap: Map): IrSimpleFunction { + return buildFun { + name = function.name + returnType = function.returnType.substitute(substitutionMap) + visibility = function.visibility + origin = IrDeclarationOrigin.IR_BUILTINS_STUB + modality = Modality.OPEN + }.apply { + // Replace Function metadata with the data from class + // Add the abstract function symbol to stub function for bridge lowering + overriddenSymbols.add(function.symbol) + parent = irClass + dispatchReceiverParameter = function.dispatchReceiverParameter?.copyWithSubstitution(this, substitutionMap) + extensionReceiverParameter = function.extensionReceiverParameter?.copyWithSubstitution(this, substitutionMap) + for (parameter in function.valueParameters) { + valueParameters.add(parameter.copyWithSubstitution(this, substitutionMap)) + } + val exception = context.getTopLevelClass(FqName("java.lang.UnsupportedOperationException")) + // Function body consist only of throwing UnsupportedOperationException statement + body = context.createIrBuilder(function.symbol).irBlockBody { + +irThrow( + irCall( + exception.owner.constructors.single { + it.valueParameters.size == 1 && it.valueParameters.single().type.isNullableString() + } + ).apply { + putValueArgument(0, irString("Operation is not supported for read-only collection")) + } + ) + } + } + } + + // Copy value parameter with type substitution + private fun IrValueParameter.copyWithSubstitution(target: IrSimpleFunction, substitutionMap: Map) + : IrValueParameter { + val descriptor = WrappedValueParameterDescriptor(this.descriptor.annotations) + return IrValueParameterImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + IrDeclarationOrigin.IR_BUILTINS_STUB, + IrValueParameterSymbolImpl(descriptor), + name, + index, + type.substitute(substitutionMap), + varargElementType?.substitute(substitutionMap), + isCrossinline, + isNoinline + ).apply { + descriptor.bind(this) + parent = target + } + } + + // Compute a substitution map for type parameters between source class (Mutable Collection classes) to + // target class (class currently in lowering phase), this map is later used for substituting type parameters in generated functions + private fun computeSubstitutionMap(readOnlyClass: IrClass, mutableClass: IrClass, targetClass: IrClass) + : Map { + // We find the most specific type for the immutable collection class from the inheritance chain of target class + // Perform type substitution along searching, then use the type arguments obtained from the most specific type + // for type substitution. + val readOnlyClassType = getAllSupertypes(targetClass).findMostSpecificTypeForClass(readOnlyClass.symbol) + val readOnlyClassTypeArguments = (readOnlyClassType as IrSimpleType).arguments.mapNotNull { (it as? IrTypeProjection)?.type } + + if (readOnlyClassTypeArguments.isEmpty() || readOnlyClassTypeArguments.size != mutableClass.typeParameters.size) { + throw IllegalStateException( + "Type argument mismatch between immutable class ${readOnlyClass.fqNameWhenAvailable}" + + " and mutable class ${mutableClass.fqNameWhenAvailable}, when processing" + + "class ${targetClass.fqNameWhenAvailable}" + ) + } + return mutableClass.typeParameters.map { it.symbol }.zip(readOnlyClassTypeArguments).toMap() + } + + private data class StubsForCollectionClass( + val readOnlyClass: IrClassSymbol, + val mutableClass: IrClassSymbol, + val mutableOnlyMethods: Collection + ) + + private val preComputedStubs: Collection by lazy { + with(context.ir.symbols) { + listOf( + collection to mutableCollection, + set to mutableSet, + list to mutableList, + map to mutableMap, + mapEntry to mutableMapEntry, + iterable to mutableIterable, + iterator to mutableIterator, + listIterator to mutableListIterator + ).map { (readOnlyClass, mutableClass) -> + val readOnlyMethodSignatures = readOnlyClass.functions.map { it.owner.toSignature() }.toHashSet() + val mutableMethods = mutableClass.functions + .map { it.owner } + .filter { it.toSignature() !in readOnlyMethodSignatures } + .toHashSet() + StubsForCollectionClass(readOnlyClass, mutableClass, mutableMethods) + } + } + } + + // Compute stubs that should be generated, compare based on signature + private fun generateRelevantStubMethods(irClass: IrClass): Set { + val ourStubsForCollectionClasses = preComputedStubs.filter { (readOnlyClass, mutableClass) -> + irClass.superTypes.any { supertypeSymbol -> + val supertype = supertypeSymbol.classOrNull?.owner + // We need to generate stub methods for following 2 cases: + // current class's direct super type is a java class or kotlin interface, and is an subtype of an immutable collection + supertype != null + && (supertype.comesFromJava() || supertype.isInterface) + && supertypeSymbol.isSubtypeOfClass(readOnlyClass) + && !irClass.symbol.isSubtypeOfClass(mutableClass) + } + } + + // do a second filtering to ensure only most relevant classes are included. + val redundantClasses = ourStubsForCollectionClasses.filter { (readOnlyClass) -> + ourStubsForCollectionClasses.any { readOnlyClass != it.readOnlyClass && it.readOnlyClass.isSubtypeOfClass(readOnlyClass) } + }.map { it.readOnlyClass } + + // perform type substitution and type erasure here + return ourStubsForCollectionClasses.filter { (readOnlyClass) -> + readOnlyClass !in redundantClasses + }.flatMap { (readOnlyClass, mutableClass, mutableOnlyMethods) -> + val substitutionMap = computeSubstitutionMap(readOnlyClass.owner, mutableClass.owner, irClass) + mutableOnlyMethods.map { function -> + createStubMethod(function, irClass, substitutionMap) + } + }.toHashSet() + } + + fun IrClass.comesFromJava() = origin in ORIGINS_FROM_JAVA + + private fun Collection.findMostSpecificTypeForClass(classifier: IrClassSymbol): IrType { + val types = this.filter { it.classifierOrNull == classifier } + if (types.isEmpty()) error("No supertype of $classifier in $this") + if (types.size == 1) return types.first() + // Find the first type in the list such that it's a subtype of every other type in that list + return types.first { type -> + types.all { other -> type.isSubtypeOfClass(other.classOrNull!!) } + } + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/builtinStubMethods/Collection.kt b/compiler/testData/codegen/box/builtinStubMethods/Collection.kt index e071af62dd5..906d1129d26 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/Collection.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/Collection.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyCollection: Collection { diff --git a/compiler/testData/codegen/box/builtinStubMethods/List.kt b/compiler/testData/codegen/box/builtinStubMethods/List.kt index fa938bcc93d..4a64bf05265 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/List.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/List.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyList: List { diff --git a/compiler/testData/codegen/box/builtinStubMethods/ListIterator.kt b/compiler/testData/codegen/box/builtinStubMethods/ListIterator.kt index 839f08e4b3a..c3bd9a90ea8 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/ListIterator.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/ListIterator.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyListIterator : ListIterator { diff --git a/compiler/testData/codegen/box/builtinStubMethods/ListWithAllImplementations.kt b/compiler/testData/codegen/box/builtinStubMethods/ListWithAllImplementations.kt index b1d2a484440..8f5988e87df 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/ListWithAllImplementations.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/ListWithAllImplementations.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyList(val v: T): List { diff --git a/compiler/testData/codegen/box/builtinStubMethods/ListWithAllInheritedImplementations.kt b/compiler/testData/codegen/box/builtinStubMethods/ListWithAllInheritedImplementations.kt index 9922ca36d41..cb1af1b6572 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/ListWithAllInheritedImplementations.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/ListWithAllInheritedImplementations.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM open class Super(val v: T) { diff --git a/compiler/testData/codegen/box/builtinStubMethods/Map.kt b/compiler/testData/codegen/box/builtinStubMethods/Map.kt index d755fc15fb7..c0324984796 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/Map.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/Map.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyMap: Map { diff --git a/compiler/testData/codegen/box/builtinStubMethods/MapEntry.kt b/compiler/testData/codegen/box/builtinStubMethods/MapEntry.kt index 9554ec2caaf..8c315a34b8d 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/MapEntry.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/MapEntry.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyMapEntry: Map.Entry { diff --git a/compiler/testData/codegen/box/builtinStubMethods/SubstitutedList.kt b/compiler/testData/codegen/box/builtinStubMethods/SubstitutedList.kt index 7d05421df5c..1ff2647b030 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/SubstitutedList.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/SubstitutedList.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyList: List { diff --git a/compiler/testData/codegen/box/builtinStubMethods/delegationToArrayList.kt b/compiler/testData/codegen/box/builtinStubMethods/delegationToArrayList.kt index 450c5cc9d1d..b9436fab469 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/delegationToArrayList.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/delegationToArrayList.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM import java.util.ArrayList diff --git a/compiler/testData/codegen/box/builtinStubMethods/immutableRemove.kt b/compiler/testData/codegen/box/builtinStubMethods/immutableRemove.kt index 286fc906a5c..32aa73212f8 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/immutableRemove.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/immutableRemove.kt @@ -1,5 +1,4 @@ // SKIP_JDK6 -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FULL_JDK // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/builtinStubMethods/implementationInTrait.kt b/compiler/testData/codegen/box/builtinStubMethods/implementationInTrait.kt index e19d8c1b4ed..c1b21f6b745 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/implementationInTrait.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/implementationInTrait.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM interface Addable { diff --git a/compiler/testData/codegen/box/builtinStubMethods/inheritedImplementations.kt b/compiler/testData/codegen/box/builtinStubMethods/inheritedImplementations.kt index bcada743b40..fd9a690ffe6 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/inheritedImplementations.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/inheritedImplementations.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM open class SetStringImpl { diff --git a/compiler/testData/codegen/box/builtinStubMethods/manyTypeParametersWithUpperBounds.kt b/compiler/testData/codegen/box/builtinStubMethods/manyTypeParametersWithUpperBounds.kt index 5feb5671a89..f906f817cce 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/manyTypeParametersWithUpperBounds.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/manyTypeParametersWithUpperBounds.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/builtinStubMethods/mapRemove/readOnlyMap.kt b/compiler/testData/codegen/box/builtinStubMethods/mapRemove/readOnlyMap.kt index 97ce3cdd5e8..3cd772bc264 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/mapRemove/readOnlyMap.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/mapRemove/readOnlyMap.kt @@ -1,5 +1,4 @@ // SKIP_JDK6 -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FULL_JDK // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/builtinStubMethods/nonTrivialSubstitution.kt b/compiler/testData/codegen/box/builtinStubMethods/nonTrivialSubstitution.kt index d968a704e2e..cdc268b382c 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/nonTrivialSubstitution.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/nonTrivialSubstitution.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM class MyCollection : Collection>> { diff --git a/compiler/testData/codegen/box/builtinStubMethods/substitutedListWithExtraSuperInterface.kt b/compiler/testData/codegen/box/builtinStubMethods/substitutedListWithExtraSuperInterface.kt index 9ce6652c196..ac7e2b3e248 100644 --- a/compiler/testData/codegen/box/builtinStubMethods/substitutedListWithExtraSuperInterface.kt +++ b/compiler/testData/codegen/box/builtinStubMethods/substitutedListWithExtraSuperInterface.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: Test.java diff --git a/compiler/testData/codegen/box/collections/noStubsInJavaSuperClass.kt b/compiler/testData/codegen/box/collections/noStubsInJavaSuperClass.kt index 533b8b3c667..465a923efeb 100644 --- a/compiler/testData/codegen/box/collections/noStubsInJavaSuperClass.kt +++ b/compiler/testData/codegen/box/collections/noStubsInJavaSuperClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: B.java