JVM_IR keep track of original overrides at collection stubs generation
KT-43068
This commit is contained in:
@@ -107,6 +107,16 @@ class JvmBackendContext(
|
||||
internal val hiddenConstructors = mutableMapOf<IrConstructor, IrConstructor>()
|
||||
|
||||
internal val collectionStubComputer = CollectionStubComputer(this)
|
||||
|
||||
private val overridesWithoutStubs = HashMap<IrSimpleFunction, List<IrSimpleFunctionSymbol>>()
|
||||
|
||||
fun recordOverridesWithoutStubs(function: IrSimpleFunction) {
|
||||
overridesWithoutStubs[function] = function.overriddenSymbols.toList()
|
||||
}
|
||||
|
||||
fun getOverridesWithoutStubs(function: IrSimpleFunction): List<IrSimpleFunctionSymbol> =
|
||||
overridesWithoutStubs.getOrElse(function) { function.overriddenSymbols }
|
||||
|
||||
internal val bridgeLoweringCache = BridgeLowering.BridgeLoweringCache(this)
|
||||
internal val functionsWithSpecialBridges: MutableSet<IrFunction> = HashSet()
|
||||
|
||||
|
||||
+27
-1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.state.JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_N
|
||||
import org.jetbrains.kotlin.codegen.state.extractTypeMappingModeFromAnnotation
|
||||
import org.jetbrains.kotlin.codegen.state.isMethodWithDeclarationSiteWildcardsFqName
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||
@@ -257,7 +258,9 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
val signature = sw.makeJvmMethodSignature(mapFunctionName(function, skipSpecial))
|
||||
|
||||
val specialSignatureInfo =
|
||||
with(BuiltinMethodsWithSpecialGenericSignature) { function.toIrBasedDescriptor().getSpecialSignatureInfo() }
|
||||
with(BuiltinMethodsWithSpecialGenericSignature) {
|
||||
function.toIrBasedDescriptorWithOriginalOverrides().getSpecialSignatureInfo()
|
||||
}
|
||||
|
||||
// Old back-end doesn't patch generic signatures if corresponding function had special bridges.
|
||||
// See org.jetbrains.kotlin.codegen.FunctionCodegen#hasSpecialBridgeMethod and its usage.
|
||||
@@ -272,6 +275,29 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
return signature
|
||||
}
|
||||
|
||||
private fun IrFunction.toIrBasedDescriptorWithOriginalOverrides(): FunctionDescriptor =
|
||||
when (this) {
|
||||
is IrConstructor ->
|
||||
toIrBasedDescriptor()
|
||||
is IrSimpleFunction ->
|
||||
if (isPropertyAccessor)
|
||||
toIrBasedDescriptor()
|
||||
else
|
||||
IrBasedSimpleFunctionDescriptorWithOriginalOverrides(this, context)
|
||||
else ->
|
||||
throw AssertionError("Unexpected function kind: $this")
|
||||
}
|
||||
|
||||
private class IrBasedSimpleFunctionDescriptorWithOriginalOverrides(
|
||||
owner: IrSimpleFunction,
|
||||
private val context: JvmBackendContext
|
||||
) : IrBasedSimpleFunctionDescriptor(owner) {
|
||||
override fun getOverriddenDescriptors(): List<FunctionDescriptor> =
|
||||
context.getOverridesWithoutStubs(owner).map {
|
||||
IrBasedSimpleFunctionDescriptorWithOriginalOverrides(it.owner, context)
|
||||
}
|
||||
}
|
||||
|
||||
// Boxing is only necessary for 'remove(E): Boolean' of a MutableCollection<Int> implementation.
|
||||
// Otherwise this method might clash with 'remove(I): E' defined in the java.util.List JDK interface (mapped to kotlin 'removeAt').
|
||||
internal fun shouldBoxSingleValueParameterForSpecialCaseOfRemove(irFunction: IrFunction): Boolean {
|
||||
|
||||
+10
-4
@@ -69,10 +69,16 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
||||
val existingOverrides = relevantMembers.filter { isEffectivelyOverriddenBy(stub, it) }
|
||||
|
||||
if (existingOverrides.isNotEmpty()) {
|
||||
// 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.
|
||||
existingOverrides.forEach { it.overriddenSymbols += stub.overriddenSymbols }
|
||||
existingOverrides.forEach {
|
||||
// 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.
|
||||
// However, we still need to keep track of the original overrides
|
||||
// so that special built-in signature mapping doesn't confuse it with a method
|
||||
// that actually requires signature patching.
|
||||
context.recordOverridesWithoutStubs(it)
|
||||
it.overriddenSymbols += stub.overriddenSymbols
|
||||
}
|
||||
// We don't add a throwing stub if it's effectively overridden by an existing function.
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -10,14 +10,15 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyProperty
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
@@ -363,9 +364,9 @@ open class IrBasedVariableDescriptorWithAccessor(owner: IrLocalDelegatedProperty
|
||||
override fun isLateInit(): Boolean = false
|
||||
|
||||
override val getter: VariableAccessorDescriptor?
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
get() = TODO("not implemented")
|
||||
override val setter: VariableAccessorDescriptor?
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
get() = TODO("not implemented")
|
||||
override val isDelegated: Boolean = true
|
||||
}
|
||||
|
||||
@@ -416,11 +417,11 @@ open class IrBasedSimpleFunctionDescriptor(owner: IrSimpleFunction) : SimpleFunc
|
||||
else CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor?,
|
||||
modality: Modality?,
|
||||
visibility: DescriptorVisibility?,
|
||||
kind: CallableMemberDescriptor.Kind?,
|
||||
copyOverrides: Boolean
|
||||
newOwner: DeclarationDescriptor?,
|
||||
modality: Modality?,
|
||||
visibility: DescriptorVisibility?,
|
||||
kind: CallableMemberDescriptor.Kind?,
|
||||
copyOverrides: Boolean
|
||||
): Nothing {
|
||||
TODO("not implemented")
|
||||
}
|
||||
@@ -484,11 +485,11 @@ open class IrBasedClassConstructorDescriptor(owner: IrConstructor) : ClassConstr
|
||||
}
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: DescriptorVisibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
newOwner: DeclarationDescriptor,
|
||||
modality: Modality,
|
||||
visibility: DescriptorVisibility,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
copyOverrides: Boolean
|
||||
): ClassConstructorDescriptor {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
@@ -556,11 +557,12 @@ open class IrBasedClassConstructorDescriptor(owner: IrConstructor) : ClassConstr
|
||||
|
||||
fun IrConstructor.toIrBasedDescriptor() = IrBasedClassConstructorDescriptor(this)
|
||||
|
||||
fun IrFunction.toIrBasedDescriptor(): FunctionDescriptor = when(this) {
|
||||
is IrSimpleFunction -> toIrBasedDescriptor()
|
||||
is IrConstructor -> toIrBasedDescriptor()
|
||||
else -> error("Unknown function kind")
|
||||
}
|
||||
fun IrFunction.toIrBasedDescriptor(): FunctionDescriptor =
|
||||
when (this) {
|
||||
is IrSimpleFunction -> toIrBasedDescriptor()
|
||||
is IrConstructor -> toIrBasedDescriptor()
|
||||
else -> error("Unknown function kind")
|
||||
}
|
||||
|
||||
open class IrBasedClassDescriptor(owner: IrClass) : ClassDescriptor, IrBasedDeclarationDescriptor<IrClass>(owner) {
|
||||
override fun getName() = owner.name
|
||||
@@ -590,7 +592,8 @@ open class IrBasedClassDescriptor(owner: IrClass) : ClassDescriptor, IrBasedDecl
|
||||
|
||||
override fun getModality() = owner.modality
|
||||
|
||||
override fun getCompanionObjectDescriptor() = owner.declarations.filterIsInstance<IrClass>().firstOrNull { it.isCompanion }?.toIrBasedDescriptor()
|
||||
override fun getCompanionObjectDescriptor() =
|
||||
owner.declarations.filterIsInstance<IrClass>().firstOrNull { it.isCompanion }?.toIrBasedDescriptor()
|
||||
|
||||
override fun getVisibility() = owner.visibility
|
||||
|
||||
@@ -778,11 +781,11 @@ open class IrBasedPropertyDescriptor(owner: IrProperty) : PropertyDescriptor, Ir
|
||||
override fun getOverriddenDescriptors(): MutableCollection<out PropertyDescriptor> = mutableListOf()
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor?,
|
||||
modality: Modality?,
|
||||
visibility: DescriptorVisibility?,
|
||||
kind: CallableMemberDescriptor.Kind?,
|
||||
copyOverrides: Boolean
|
||||
newOwner: DeclarationDescriptor?,
|
||||
modality: Modality?,
|
||||
visibility: DescriptorVisibility?,
|
||||
kind: CallableMemberDescriptor.Kind?,
|
||||
copyOverrides: Boolean
|
||||
): CallableMemberDescriptor {
|
||||
TODO("not implemented")
|
||||
}
|
||||
@@ -822,13 +825,15 @@ open class IrBasedPropertyDescriptor(owner: IrProperty) : PropertyDescriptor, Ir
|
||||
|
||||
override fun isVar() = owner.isVar
|
||||
|
||||
override fun getDispatchReceiverParameter() = owner.getter?.dispatchReceiverParameter?.toIrBasedDescriptor() as? ReceiverParameterDescriptor
|
||||
override fun getDispatchReceiverParameter() =
|
||||
owner.getter?.dispatchReceiverParameter?.toIrBasedDescriptor() as? ReceiverParameterDescriptor
|
||||
|
||||
override fun isConst() = owner.isConst
|
||||
|
||||
override fun isLateInit() = owner.isLateinit
|
||||
|
||||
override fun getExtensionReceiverParameter() = owner.getter?.extensionReceiverParameter?.toIrBasedDescriptor() as? ReceiverParameterDescriptor
|
||||
override fun getExtensionReceiverParameter() =
|
||||
owner.getter?.extensionReceiverParameter?.toIrBasedDescriptor() as? ReceiverParameterDescriptor
|
||||
|
||||
override fun isExternal() = owner.isExternal
|
||||
|
||||
@@ -973,11 +978,11 @@ open class IrBasedFieldDescriptor(owner: IrField) : PropertyDescriptor, IrBasedD
|
||||
override fun getOverriddenDescriptors(): MutableCollection<out PropertyDescriptor> = mutableListOf()
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor?,
|
||||
modality: Modality?,
|
||||
visibility: DescriptorVisibility?,
|
||||
kind: CallableMemberDescriptor.Kind?,
|
||||
copyOverrides: Boolean
|
||||
newOwner: DeclarationDescriptor?,
|
||||
modality: Modality?,
|
||||
visibility: DescriptorVisibility?,
|
||||
kind: CallableMemberDescriptor.Kind?,
|
||||
copyOverrides: Boolean
|
||||
): CallableMemberDescriptor {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// WITH_SIGNATURES
|
||||
|
||||
class MyList<T>(val v: T): List<T> {
|
||||
override val size: Int get() = 0
|
||||
override fun isEmpty(): Boolean = true
|
||||
override fun contains(o: T): Boolean = false
|
||||
override fun iterator(): Iterator<T> = throw Error()
|
||||
override fun containsAll(c: Collection<T>): Boolean = false
|
||||
override fun get(index: Int): T = v
|
||||
override fun indexOf(o: T): Int = -1
|
||||
override fun lastIndexOf(o: T): Int = -1
|
||||
override fun listIterator(): ListIterator<T> = throw Error()
|
||||
override fun listIterator(index: Int): ListIterator<T> = throw Error()
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<T> = throw Error()
|
||||
override fun hashCode(): Int = 0
|
||||
override fun equals(other: Any?): Boolean = false
|
||||
|
||||
public fun add(e: T): Boolean = true
|
||||
public fun remove(o: T): Boolean = true
|
||||
public fun addAll(c: Collection<T>): Boolean = true
|
||||
public fun addAll(index: Int, c: Collection<T>): Boolean = true
|
||||
public fun removeAll(c: Collection<T>): Boolean = true
|
||||
public fun retainAll(c: Collection<T>): Boolean = true
|
||||
public fun clear() {}
|
||||
public fun set(index: Int, element: T): T = element
|
||||
public fun add(index: Int, element: T) {}
|
||||
public fun removeAt(index: Int): T = v
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
@kotlin.Metadata
|
||||
public final class<<T:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/List<TT;>;Lkotlin/jvm/internal/markers/KMappedMarker;> MyList {
|
||||
// source: 'stubLikeMethodSignatures.kt'
|
||||
public @org.jetbrains.annotations.NotNull <()Ljava/util/Iterator<TT;>;> method iterator(): java.util.Iterator
|
||||
public @org.jetbrains.annotations.NotNull <()Ljava/util/ListIterator<TT;>;> method listIterator(): java.util.ListIterator
|
||||
public final <()TT;> method getV(): java.lang.Object
|
||||
public @org.jetbrains.annotations.NotNull <(I)Ljava/util/ListIterator<TT;>;> method listIterator(p0: int): java.util.ListIterator
|
||||
public <(I)TT;> method get(p0: int): java.lang.Object
|
||||
public bridge final <(I)TT;> method remove(p0: int): java.lang.Object
|
||||
public final <(I)TT;> method removeAt(p0: int): java.lang.Object
|
||||
public @org.jetbrains.annotations.NotNull <(II)Ljava/util/List<TT;>;> method subList(p0: int, p1: int): java.util.List
|
||||
public final <(ILjava/util/Collection<+TT;>;)Z> method addAll(p0: int, @org.jetbrains.annotations.NotNull p1: java.util.Collection): boolean
|
||||
public final <(ITT;)TT;> method set(p0: int, p1: java.lang.Object): java.lang.Object
|
||||
public final <(ITT;)V> method add(p0: int, p1: java.lang.Object): void
|
||||
public <(Ljava/util/Collection<+Ljava/lang/Object;>;)Z> method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
|
||||
public final <(Ljava/util/Collection<+TT;>;)Z> method addAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
|
||||
public final <(Ljava/util/Collection<+TT;>;)Z> method removeAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
|
||||
public final <(Ljava/util/Collection<+TT;>;)Z> method retainAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean
|
||||
public <(TT;)V> method <init>(p0: java.lang.Object): void
|
||||
public final <(TT;)Z> method add(p0: java.lang.Object): boolean
|
||||
public final <(TT;)Z> method remove(p0: java.lang.Object): boolean
|
||||
public <<T:Ljava/lang/Object;>([TT;)[TT;> method toArray(p0: java.lang.Object[]): java.lang.Object[]
|
||||
public final <null> method clear(): void
|
||||
public <null> method contains(p0: java.lang.Object): boolean
|
||||
public <null> method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public <null> method getSize(): int
|
||||
public <null> method hashCode(): int
|
||||
public <null> method indexOf(p0: java.lang.Object): int
|
||||
public <null> method isEmpty(): boolean
|
||||
public <null> method lastIndexOf(p0: java.lang.Object): int
|
||||
public bridge final <null> method size(): int
|
||||
public <null> method toArray(): java.lang.Object[]
|
||||
private final field <TT;> v: java.lang.Object
|
||||
}
|
||||
+5
@@ -419,6 +419,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/stubForAbstractFunWithCovariantOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stubLikeMethodSignatures.kt")
|
||||
public void testStubLikeMethodSignatures() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/stubLikeMethodSignatures.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stubsFromSuperclass.kt")
|
||||
public void testStubsFromSuperclass() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/stubsFromSuperclass.kt");
|
||||
|
||||
+5
@@ -419,6 +419,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
|
||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/stubForAbstractFunWithCovariantOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stubLikeMethodSignatures.kt")
|
||||
public void testStubLikeMethodSignatures() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/stubLikeMethodSignatures.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stubsFromSuperclass.kt")
|
||||
public void testStubsFromSuperclass() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/stubsFromSuperclass.kt");
|
||||
|
||||
Reference in New Issue
Block a user