JVM_IR more precise superclass stub filtering
Filter out abstract members of superclasses when generating collection stubs. KT-43207
This commit is contained in:
+138
-94
@@ -66,7 +66,7 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
|||||||
for (stub in methodStubsToGenerate) {
|
for (stub in methodStubsToGenerate) {
|
||||||
val stubNameAndArity = stub.nameAndArity
|
val stubNameAndArity = stub.nameAndArity
|
||||||
val relevantMembers = nonAbstractMethodsByNameAndArity[stubNameAndArity].orEmpty()
|
val relevantMembers = nonAbstractMethodsByNameAndArity[stubNameAndArity].orEmpty()
|
||||||
val existingOverrides = relevantMembers.filter { isOverriddenBy(stub, it) }
|
val existingOverrides = relevantMembers.filter { isEffectivelyOverriddenBy(stub, it) }
|
||||||
|
|
||||||
if (existingOverrides.isNotEmpty()) {
|
if (existingOverrides.isNotEmpty()) {
|
||||||
// In the case that we find a defined method that matches the stub signature,
|
// In the case that we find a defined method that matches the stub signature,
|
||||||
@@ -78,7 +78,8 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generated stub might still override some abstract member(s), which affects resulting method signature.
|
// Generated stub might still override some abstract member(s), which affects resulting method signature.
|
||||||
val overriddenAbstractMethods = abstractMethodsByNameAndArity[stubNameAndArity].orEmpty().filter { isOverriddenBy(it, stub) }
|
val overriddenAbstractMethods = abstractMethodsByNameAndArity[stubNameAndArity].orEmpty()
|
||||||
|
.filter { isEffectivelyOverriddenBy(it, stub) }
|
||||||
stub.overriddenSymbols += overriddenAbstractMethods.map { it.symbol }
|
stub.overriddenSymbols += overriddenAbstractMethods.map { it.symbol }
|
||||||
|
|
||||||
// Some stub members require special handling.
|
// Some stub members require special handling.
|
||||||
@@ -121,8 +122,6 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
|||||||
else ->
|
else ->
|
||||||
irClass.declarations.add(stub)
|
irClass.declarations.add(stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +195,7 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isOverriddenBy(superFun: IrSimpleFunction, overridingFun: IrSimpleFunction): Boolean {
|
private fun isEffectivelyOverriddenBy(superFun: IrSimpleFunction, overridingFun: IrSimpleFunction): Boolean {
|
||||||
// Function 'f0' is overridden by function 'f1' if all of the following conditions are met,
|
// Function 'f0' is overridden by function 'f1' if all of the following conditions are met,
|
||||||
// assuming type parameter Ti of 'f1' is "equal" to type parameter Si of 'f0':
|
// assuming type parameter Ti of 'f1' is "equal" to type parameter Si of 'f0':
|
||||||
// - names are same;
|
// - names are same;
|
||||||
@@ -301,34 +300,69 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
|||||||
|
|
||||||
// Compute stubs that should be generated, compare based on signature
|
// Compute stubs that should be generated, compare based on signature
|
||||||
private fun generateRelevantStubMethods(irClass: IrClass): List<IrSimpleFunction> {
|
private fun generateRelevantStubMethods(irClass: IrClass): List<IrSimpleFunction> {
|
||||||
fun createStubFuns(stubs: StubsForCollectionClass): List<IrSimpleFunction> {
|
val classStubFuns = collectionStubComputer.stubsForCollectionClasses(irClass)
|
||||||
val (readOnlyClass, mutableClass, candidatesForStubs) = stubs
|
.flatMap { createStubFuns(irClass, it) }
|
||||||
val substitutionMap = computeSubstitutionMap(readOnlyClass.owner, mutableClass.owner, irClass)
|
|
||||||
return candidatesForStubs.map { function ->
|
|
||||||
createStubMethod(function, irClass, substitutionMap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val classStubs = collectionStubComputer.stubsForCollectionClasses(irClass)
|
val superClassStubSignatures = computeStubsForSuperClasses(irClass)
|
||||||
|
.flatMap { createStubFuns(irClass, it) }
|
||||||
val superClassesStubs = irClass.superClass?.run {
|
.mapTo(HashSet()) { it.toJvmSignature() }
|
||||||
superClassChain.flatMap { superClass ->
|
|
||||||
collectionStubComputer.stubsForCollectionClasses(superClass)
|
|
||||||
}.toList()
|
|
||||||
} ?: emptyList()
|
|
||||||
|
|
||||||
val relevantStubs =
|
|
||||||
classStubs.filter { (readOnlyClass) ->
|
|
||||||
classStubs.none { readOnlyClass != it.readOnlyClass && it.readOnlyClass.isSubtypeOfClass(readOnlyClass) } &&
|
|
||||||
superClassesStubs.none { it.readOnlyClass == readOnlyClass }
|
|
||||||
}
|
|
||||||
|
|
||||||
val classStubFuns = relevantStubs.flatMap { createStubFuns(it) }
|
|
||||||
val superClassStubSignatures = superClassesStubs.flatMap { createStubFuns(it) }.mapTo(HashSet()) { it.toJvmSignature() }
|
|
||||||
|
|
||||||
return classStubFuns.filter { it.toJvmSignature() !in superClassStubSignatures }
|
return classStubFuns.filter { it.toJvmSignature() !in superClassStubSignatures }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createStubFuns(irClass: IrClass, stubs: StubsForCollectionClass): List<IrSimpleFunction> {
|
||||||
|
val (readOnlyClass, mutableClass, candidatesForStubs) = stubs
|
||||||
|
val substitutionMap = computeSubstitutionMap(readOnlyClass.owner, mutableClass.owner, irClass)
|
||||||
|
return candidatesForStubs.map { function ->
|
||||||
|
createStubMethod(function, irClass, substitutionMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeStubsForSuperClasses(irClass: IrClass): List<StubsForCollectionClass> {
|
||||||
|
val immediateSuperClass = irClass.superClass ?: return emptyList()
|
||||||
|
return immediateSuperClass.superClassChain
|
||||||
|
.flatMap { superClass -> computeStubsForSuperClass(superClass) }
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FilteredStubsForCollectionClass(
|
||||||
|
override val readOnlyClass: IrClassSymbol,
|
||||||
|
override val mutableClass: IrClassSymbol,
|
||||||
|
override val candidatesForStubs: Collection<IrSimpleFunction>
|
||||||
|
) : StubsForCollectionClass
|
||||||
|
|
||||||
|
private fun computeStubsForSuperClass(superClass: IrClass): List<StubsForCollectionClass> {
|
||||||
|
val superClassStubs = collectionStubComputer.stubsForCollectionClasses(superClass)
|
||||||
|
|
||||||
|
if (superClass.modality != Modality.ABSTRACT) return superClassStubs
|
||||||
|
|
||||||
|
// An abstract superclass might contain an abstract function declaration that effectively overrides a stub to be generated,
|
||||||
|
// and thus have no non-abstract stub.
|
||||||
|
// This calculation happens for each abstract class multiple times. TODO memoize.
|
||||||
|
|
||||||
|
val abstractFunsByNameAndArity = superClass.functions
|
||||||
|
.filter { !it.isFakeOverride && it.modality == Modality.ABSTRACT }
|
||||||
|
.groupBy { it.nameAndArity }
|
||||||
|
|
||||||
|
if (abstractFunsByNameAndArity.isEmpty()) return superClassStubs
|
||||||
|
|
||||||
|
return superClassStubs.map {
|
||||||
|
val (readOnlyClass, mutableClass, candidatesForStubs) = it
|
||||||
|
// NB here we should build a stub in substitution context of the given superclass.
|
||||||
|
// Resulting stub can be different from a stub created in substitution context of the "current" class
|
||||||
|
// in case of (partially) specialized generic superclass.
|
||||||
|
val substitutionMap = computeSubstitutionMap(readOnlyClass.owner, mutableClass.owner, superClass)
|
||||||
|
val filteredCandidates = candidatesForStubs.filter { candidateFun ->
|
||||||
|
val stubMethod = createStubMethod(candidateFun, superClass, substitutionMap)
|
||||||
|
val stubNameAndArity = stubMethod.nameAndArity
|
||||||
|
abstractFunsByNameAndArity[stubNameAndArity].orEmpty().none { abstractFun ->
|
||||||
|
isEffectivelyOverriddenBy(stubMethod, abstractFun)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FilteredStubsForCollectionClass(readOnlyClass, mutableClass, filteredCandidates)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun Collection<IrType>.findMostSpecificTypeForClass(classifier: IrClassSymbol): IrType {
|
private fun Collection<IrType>.findMostSpecificTypeForClass(classifier: IrClassSymbol): IrType {
|
||||||
val types = this.filter { it.classifierOrNull == classifier }
|
val types = this.filter { it.classifierOrNull == classifier }
|
||||||
if (types.isEmpty()) error("No supertype of $classifier in $this")
|
if (types.isEmpty()) error("No supertype of $classifier in $this")
|
||||||
@@ -346,85 +380,95 @@ internal class CollectionStubMethodLowering(val context: JvmBackendContext) : Cl
|
|||||||
get() = generateSequence(this) { it.superClass }
|
get() = generateSequence(this) { it.superClass }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal interface StubsForCollectionClass {
|
||||||
internal class StubsForCollectionClass(
|
val readOnlyClass: IrClassSymbol
|
||||||
val readOnlyClass: IrClassSymbol,
|
|
||||||
val mutableClass: IrClassSymbol
|
val mutableClass: IrClassSymbol
|
||||||
) {
|
val candidatesForStubs: Collection<IrSimpleFunction>
|
||||||
// Old back-end generates stubs for 'class A : C', where
|
|
||||||
// 'C' is some "read-only collection" interface from kotlin.collections,
|
|
||||||
// 'MC' is a corresponding "mutable collection" interface from kotlin.collections,
|
|
||||||
// by building fake overrides for a special 'class X : A(), MC'
|
|
||||||
// and taking fake overrides that override members from 'MC'.
|
|
||||||
//
|
|
||||||
// Here we are looking at this problem from a slightly different angle:
|
|
||||||
// we select suitable member functions 'f' in 'MC' that might potentially require stubs (we are here!),
|
|
||||||
// and then we generate stubs for functions 'f' that are not effectively overridden by members of 'A'
|
|
||||||
// (this happens in the lowering itself).
|
|
||||||
//
|
|
||||||
// In order for this to be equivalent to the old back-end approach,
|
|
||||||
// we should take 'f' in 'MC' such that any of the following conditions is true:
|
|
||||||
// - 'f' is declared in 'MC' - that is, 'f' itself is not a fake override;
|
|
||||||
// - 'f' is abstract and doesn't override anything from 'C'.
|
|
||||||
//
|
|
||||||
// NB1 it also covers default methods from JDK collection classes case
|
|
||||||
// (since that's the only way a member function in 'MC' might be non-abstract).
|
|
||||||
//
|
|
||||||
// NB2 the scheme of stub method generation in the old back-end depends too much on
|
|
||||||
// which particular declarations are present in 'MC'.
|
|
||||||
// Some of these declarations are redundant from the stub generation point of view -
|
|
||||||
// for example, 'kotlin.collections.MutableListIterator' contains the following (redundant) declarations:
|
|
||||||
// override fun next(): T
|
|
||||||
// override fun hasNext(): Boolean
|
|
||||||
// which cause stubs for 'next' and 'hasNext' to be generated in a 'abstract class A<T> : ListIterator<T>'.
|
|
||||||
// See https://youtrack.jetbrains.com/issue/KT-36724.
|
|
||||||
// In the ideal world, it should be enough to check that
|
|
||||||
// the given member function 'f' from 'MC' doesn't override anything from 'C'.
|
|
||||||
val candidatesForStubs: Collection<IrSimpleFunction> by lazy {
|
|
||||||
mutableClass.functions
|
|
||||||
.map { it.owner }
|
|
||||||
.filter { memberFun ->
|
|
||||||
!memberFun.isFakeOverride ||
|
|
||||||
(memberFun.modality == Modality.ABSTRACT && memberFun.overriddenSymbols.none { overriddenFun ->
|
|
||||||
overriddenFun.owner.parentAsClass.symbol == readOnlyClass
|
|
||||||
})
|
|
||||||
}
|
|
||||||
.toHashSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun component1() = readOnlyClass
|
|
||||||
operator fun component2() = mutableClass
|
|
||||||
operator fun component3() = candidatesForStubs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal operator fun StubsForCollectionClass.component1() = readOnlyClass
|
||||||
|
internal operator fun StubsForCollectionClass.component2() = mutableClass
|
||||||
|
internal operator fun StubsForCollectionClass.component3() = candidatesForStubs
|
||||||
|
|
||||||
internal class CollectionStubComputer(val context: JvmBackendContext) {
|
internal class CollectionStubComputer(val context: JvmBackendContext) {
|
||||||
|
|
||||||
|
private class LazyStubsForCollectionClass(
|
||||||
|
override val readOnlyClass: IrClassSymbol,
|
||||||
|
override val mutableClass: IrClassSymbol
|
||||||
|
) : StubsForCollectionClass {
|
||||||
|
override val candidatesForStubs: Collection<IrSimpleFunction> by lazy {
|
||||||
|
// Old back-end generates stubs for 'class A : C', where
|
||||||
|
// 'C' is some "read-only collection" interface from kotlin.collections,
|
||||||
|
// 'MC' is a corresponding "mutable collection" interface from kotlin.collections,
|
||||||
|
// by building fake overrides for a special 'class X : A(), MC'
|
||||||
|
// and taking fake overrides that override members from 'MC'.
|
||||||
|
//
|
||||||
|
// Here we are looking at this problem from a slightly different angle:
|
||||||
|
// we select suitable member functions 'f' in 'MC' that might potentially require stubs (we are here!),
|
||||||
|
// and then we generate stubs for functions 'f' that are not effectively overridden by members of 'A'
|
||||||
|
// (this happens in the lowering itself).
|
||||||
|
//
|
||||||
|
// In order for this to be equivalent to the old back-end approach,
|
||||||
|
// we should take 'f' in 'MC' such that any of the following conditions is true:
|
||||||
|
// - 'f' is declared in 'MC' - that is, 'f' itself is not a fake override;
|
||||||
|
// - 'f' is abstract and doesn't override anything from 'C'.
|
||||||
|
//
|
||||||
|
// NB1 it also covers default methods from JDK collection classes case
|
||||||
|
// (since that's the only way a member function in 'MC' might be non-abstract).
|
||||||
|
//
|
||||||
|
// NB2 the scheme of stub method generation in the old back-end depends too much on
|
||||||
|
// which particular declarations are present in 'MC'.
|
||||||
|
// Some of these declarations are redundant from the stub generation point of view -
|
||||||
|
// for example, 'kotlin.collections.MutableListIterator' contains the following (redundant) declarations:
|
||||||
|
// override fun next(): T
|
||||||
|
// override fun hasNext(): Boolean
|
||||||
|
// which cause stubs for 'next' and 'hasNext' to be generated in a 'abstract class A<T> : ListIterator<T>'.
|
||||||
|
// See https://youtrack.jetbrains.com/issue/KT-36724.
|
||||||
|
// In the ideal world, it should be enough to check that
|
||||||
|
// the given member function 'f' from 'MC' doesn't override anything from 'C'.
|
||||||
|
|
||||||
|
mutableClass.functions
|
||||||
|
.map { it.owner }
|
||||||
|
.filter { memberFun ->
|
||||||
|
!memberFun.isFakeOverride ||
|
||||||
|
(memberFun.modality == Modality.ABSTRACT && memberFun.overriddenSymbols.none { overriddenFun ->
|
||||||
|
overriddenFun.owner.parentAsClass.symbol == readOnlyClass
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.toHashSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val preComputedStubs: Collection<StubsForCollectionClass> by lazy {
|
private val preComputedStubs: Collection<StubsForCollectionClass> by lazy {
|
||||||
with(context.ir.symbols) {
|
with(context.ir.symbols) {
|
||||||
listOf(
|
listOf(
|
||||||
collection to mutableCollection,
|
LazyStubsForCollectionClass(collection, mutableCollection),
|
||||||
set to mutableSet,
|
LazyStubsForCollectionClass(set, mutableSet),
|
||||||
list to mutableList,
|
LazyStubsForCollectionClass(list, mutableList),
|
||||||
map to mutableMap,
|
LazyStubsForCollectionClass(map, mutableMap),
|
||||||
mapEntry to mutableMapEntry,
|
LazyStubsForCollectionClass(mapEntry, mutableMapEntry),
|
||||||
iterable to mutableIterable,
|
LazyStubsForCollectionClass(iterable, mutableIterable),
|
||||||
iterator to mutableIterator,
|
LazyStubsForCollectionClass(iterator, mutableIterator),
|
||||||
listIterator to mutableListIterator
|
LazyStubsForCollectionClass(listIterator, mutableListIterator)
|
||||||
).map { (readOnlyClass, mutableClass) ->
|
)
|
||||||
StubsForCollectionClass(readOnlyClass, mutableClass)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val stubsCache = mutableMapOf<IrClass, Collection<StubsForCollectionClass>>()
|
private val stubsCache = mutableMapOf<IrClass, List<StubsForCollectionClass>>()
|
||||||
|
|
||||||
fun stubsForCollectionClasses(irClass: IrClass): Collection<StubsForCollectionClass> =
|
fun stubsForCollectionClasses(irClass: IrClass): List<StubsForCollectionClass> =
|
||||||
stubsCache.getOrPut(irClass) {
|
stubsCache.getOrPut(irClass) {
|
||||||
if (irClass.isFromJava()) emptySet()
|
computeStubsForCollectionClasses(irClass)
|
||||||
else preComputedStubs.filter { (readOnlyClass, mutableClass) ->
|
|
||||||
!irClass.symbol.isSubtypeOfClass(mutableClass) &&
|
|
||||||
irClass.superTypes.any { it.isSubtypeOfClass(readOnlyClass) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun computeStubsForCollectionClasses(irClass: IrClass): List<StubsForCollectionClass> {
|
||||||
|
if (irClass.isFromJava()) return emptyList()
|
||||||
|
val stubs = preComputedStubs.filter { (readOnlyClass, mutableClass) ->
|
||||||
|
!irClass.symbol.isSubtypeOfClass(mutableClass) &&
|
||||||
|
irClass.superTypes.any { it.isSubtypeOfClass(readOnlyClass) }
|
||||||
|
}
|
||||||
|
return stubs.filter { (readOnlyClass) ->
|
||||||
|
stubs.none { readOnlyClass != it.readOnlyClass && it.readOnlyClass.isSubtypeOfClass(readOnlyClass) }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
abstract class AIterD : AbstractIterator<Double>()
|
||||||
|
|
||||||
|
abstract class ACollD : AbstractCollection<Double>()
|
||||||
|
|
||||||
|
abstract class AMCollD : AbstractMutableCollection<Double>()
|
||||||
|
|
||||||
|
abstract class ASetD : AbstractSet<Double>()
|
||||||
|
|
||||||
|
abstract class AMSetD : AbstractMutableSet<Double>()
|
||||||
|
|
||||||
|
abstract class AListD : AbstractList<Double>()
|
||||||
|
|
||||||
Vendored
+54
@@ -0,0 +1,54 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class ACollD {
|
||||||
|
// source: 'inheritingFromAbstractCollections.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge method contains(p0: double): boolean
|
||||||
|
public bridge final method contains(p0: java.lang.Object): boolean
|
||||||
|
public method iterator(): java.util.Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AIterD {
|
||||||
|
// source: 'inheritingFromAbstractCollections.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AListD {
|
||||||
|
// source: 'inheritingFromAbstractCollections.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge method contains(p0: double): boolean
|
||||||
|
public bridge final method contains(p0: java.lang.Object): boolean
|
||||||
|
public bridge method indexOf(p0: double): int
|
||||||
|
public bridge final method indexOf(p0: java.lang.Object): int
|
||||||
|
public bridge method lastIndexOf(p0: double): int
|
||||||
|
public bridge final method lastIndexOf(p0: java.lang.Object): int
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMCollD {
|
||||||
|
// source: 'inheritingFromAbstractCollections.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge method contains(p0: double): boolean
|
||||||
|
public bridge final method contains(p0: java.lang.Object): boolean
|
||||||
|
public bridge method remove(p0: double): boolean
|
||||||
|
public bridge final method remove(p0: java.lang.Object): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMSetD {
|
||||||
|
// source: 'inheritingFromAbstractCollections.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge method contains(p0: double): boolean
|
||||||
|
public bridge final method contains(p0: java.lang.Object): boolean
|
||||||
|
public bridge method remove(p0: double): boolean
|
||||||
|
public bridge final method remove(p0: java.lang.Object): boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class ASetD {
|
||||||
|
// source: 'inheritingFromAbstractCollections.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge method contains(p0: double): boolean
|
||||||
|
public bridge final method contains(p0: java.lang.Object): boolean
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
abstract class AMapSD : AbstractMap<String, Double>()
|
||||||
|
|
||||||
|
abstract class AMMapSD : AbstractMutableMap<String, Double>()
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMMapSD {
|
||||||
|
// source: 'inheritingFromAbstractMap.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge final method containsKey(p0: java.lang.Object): boolean
|
||||||
|
public bridge method containsKey(p0: java.lang.String): boolean
|
||||||
|
public bridge method containsValue(p0: double): boolean
|
||||||
|
public bridge final method containsValue(p0: java.lang.Object): boolean
|
||||||
|
public bridge final method get(p0: java.lang.Object): java.lang.Object
|
||||||
|
public bridge method get(p0: java.lang.String): java.lang.Double
|
||||||
|
public bridge final method remove(p0: java.lang.Object): java.lang.Object
|
||||||
|
public bridge method remove(p0: java.lang.String): java.lang.Double
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMapSD {
|
||||||
|
// source: 'inheritingFromAbstractMap.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge final method containsKey(p0: java.lang.Object): boolean
|
||||||
|
public bridge method containsKey(p0: java.lang.String): boolean
|
||||||
|
public bridge method containsValue(p0: double): boolean
|
||||||
|
public bridge final method containsValue(p0: java.lang.Object): boolean
|
||||||
|
public bridge final method get(p0: java.lang.Object): java.lang.Object
|
||||||
|
public bridge method get(p0: java.lang.String): java.lang.Double
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMMapSD {
|
||||||
|
// source: 'inheritingFromAbstractMap.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge final method containsKey(p0: java.lang.Object): boolean
|
||||||
|
public bridge method containsKey(p0: java.lang.String): boolean
|
||||||
|
public bridge method containsValue(p0: double): boolean
|
||||||
|
public bridge final method containsValue(p0: java.lang.Object): boolean
|
||||||
|
public bridge final method get(p0: java.lang.Object): java.lang.Double
|
||||||
|
public bridge method get(p0: java.lang.String): java.lang.Double
|
||||||
|
public bridge final method remove(p0: java.lang.Object): java.lang.Double
|
||||||
|
public bridge method remove(p0: java.lang.String): java.lang.Double
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMapSD {
|
||||||
|
// source: 'inheritingFromAbstractMap.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge final method containsKey(p0: java.lang.Object): boolean
|
||||||
|
public bridge method containsKey(p0: java.lang.String): boolean
|
||||||
|
public bridge method containsValue(p0: double): boolean
|
||||||
|
public bridge final method containsValue(p0: java.lang.Object): boolean
|
||||||
|
public bridge final method get(p0: java.lang.Object): java.lang.Double
|
||||||
|
public bridge method get(p0: java.lang.String): java.lang.Double
|
||||||
|
}
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
abstract class AMListD : AbstractMutableList<Double>()
|
||||||
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMListD {
|
||||||
|
// source: 'inheritingFromAbstractMutableList.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge method contains(p0: double): boolean
|
||||||
|
public bridge final method contains(p0: java.lang.Object): boolean
|
||||||
|
public bridge method indexOf(p0: double): int
|
||||||
|
public bridge final method indexOf(p0: java.lang.Object): int
|
||||||
|
public bridge method lastIndexOf(p0: double): int
|
||||||
|
public bridge final method lastIndexOf(p0: java.lang.Object): int
|
||||||
|
public bridge method remove(p0: double): boolean
|
||||||
|
public bridge final method remove(p0: int): double
|
||||||
|
public bridge final method remove(p0: java.lang.Object): boolean
|
||||||
|
public synthetic bridge method removeAt(p0: int): java.lang.Object
|
||||||
|
}
|
||||||
Vendored
+16
@@ -0,0 +1,16 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
public abstract class AMListD {
|
||||||
|
// source: 'inheritingFromAbstractMutableList.kt'
|
||||||
|
public method <init>(): void
|
||||||
|
public bridge method contains(p0: double): boolean
|
||||||
|
public bridge final method contains(p0: java.lang.Object): boolean
|
||||||
|
public bridge method indexOf(p0: double): int
|
||||||
|
public bridge final method indexOf(p0: java.lang.Object): int
|
||||||
|
public bridge method lastIndexOf(p0: double): int
|
||||||
|
public bridge final method lastIndexOf(p0: java.lang.Object): int
|
||||||
|
public bridge method remove(p0: double): boolean
|
||||||
|
public bridge final method remove(p0: int): double
|
||||||
|
public bridge final method remove(p0: java.lang.Object): boolean
|
||||||
|
public abstract method removeAt(p0: int): java.lang.Double
|
||||||
|
public synthetic bridge method removeAt(p0: int): java.lang.Object
|
||||||
|
}
|
||||||
+15
@@ -339,6 +339,21 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/extendingAbstractCollection.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/extendingAbstractCollection.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritingFromAbstractCollections.kt")
|
||||||
|
public void testInheritingFromAbstractCollections() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractCollections.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritingFromAbstractMap.kt")
|
||||||
|
public void testInheritingFromAbstractMap() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractMap.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritingFromAbstractMutableList.kt")
|
||||||
|
public void testInheritingFromAbstractMutableList() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractMutableList.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("mapOfPrimitivesFullJdk.kt")
|
@TestMetadata("mapOfPrimitivesFullJdk.kt")
|
||||||
public void testMapOfPrimitivesFullJdk() throws Exception {
|
public void testMapOfPrimitivesFullJdk() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt");
|
||||||
|
|||||||
+15
@@ -339,6 +339,21 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/extendingAbstractCollection.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/extendingAbstractCollection.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritingFromAbstractCollections.kt")
|
||||||
|
public void testInheritingFromAbstractCollections() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractCollections.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritingFromAbstractMap.kt")
|
||||||
|
public void testInheritingFromAbstractMap() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractMap.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritingFromAbstractMutableList.kt")
|
||||||
|
public void testInheritingFromAbstractMutableList() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/inheritingFromAbstractMutableList.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("mapOfPrimitivesFullJdk.kt")
|
@TestMetadata("mapOfPrimitivesFullJdk.kt")
|
||||||
public void testMapOfPrimitivesFullJdk() throws Exception {
|
public void testMapOfPrimitivesFullJdk() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/collectionStubs/mapOfPrimitivesFullJdk.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user