FIR2IR: extract fake override generator

This commit is contained in:
Mikhail Glukhikh
2020-03-02 18:39:33 +03:00
parent 0bb3a42ceb
commit 50c4c3f4fb
7 changed files with 158 additions and 141 deletions
@@ -394,6 +394,7 @@ class Fir2IrDeclarationStorage(
val callableId = firBasedSymbol.callableId
val parentClassId = callableId.classId
return if (parentClassId != null) {
// TODO: this will never work for local classes
val parentFirSymbol = firSymbolProvider.getClassLikeSymbolByFqName(parentClassId)
if (parentFirSymbol is FirClassSymbol) {
val parentIrSymbol = getIrClassSymbol(parentFirSymbol)
@@ -0,0 +1,136 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.fir.backend
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.visibility
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.buildUseSiteMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.name.Name
class Fir2IrFakeOverrideGenerator(
private val session: FirSession,
private val declarationStorage: Fir2IrDeclarationStorage,
private val conversionScope: Fir2IrConversionScope,
private val fakeOverrideMode: FakeOverrideMode
) {
private fun IrSimpleFunction.withFunction(f: IrSimpleFunction.() -> Unit): IrSimpleFunction {
return conversionScope.withFunction(conversionScope.applyParentFromStackTo(this), f)
}
private fun IrProperty.withProperty(f: IrProperty.() -> Unit): IrProperty {
return conversionScope.withProperty(conversionScope.applyParentFromStackTo(this), f)
}
private fun IrProperty.setOverriddenSymbolsForAccessors(
property: FirProperty,
firOverriddenSymbol: FirPropertySymbol
): IrProperty {
val firOverriddenProperty = firOverriddenSymbol.fir
val overriddenProperty = declarationStorage.getIrProperty(
firOverriddenProperty, declarationStorage.findIrParent(firOverriddenProperty)
)
getter?.apply {
overriddenProperty.getter?.symbol?.let { overriddenSymbols = listOf(it) }
}
if (property.isVar) {
setter?.apply {
overriddenProperty.setter?.symbol?.let { overriddenSymbols = listOf(it) }
}
}
return this
}
fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableList<Name>) {
if (fakeOverrideMode == FakeOverrideMode.NONE) return
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes(session)
val useSiteMemberScope = (klass as? FirRegularClass)?.buildUseSiteMemberScope(session, ScopeSession()) ?: return
for (name in superTypesCallableNames) {
if (name in processedCallableNames) continue
processedCallableNames += name
useSiteMemberScope.processFunctionsByName(name) { functionSymbol ->
if (functionSymbol is FirNamedFunctionSymbol) {
val originalFunction = functionSymbol.fir
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
if (functionSymbol.isFakeOverride) {
// Substitution case
val baseSymbol = functionSymbol.deepestOverriddenSymbol() as FirNamedFunctionSymbol
val irFunction = declarationStorage.getIrFunction(
// TODO: parents for functions and properties should be consistent
originalFunction, declarationStorage.findIrParent(baseSymbol.fir),
origin = origin, shouldLeaveScope = true
)
// In fake overrides, parent logic is a bit specific, because
// parent of *original* function (base class) is used for dispatch receiver,
// but fake override itself uses parent from its containing (derived) class
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(baseSymbol) as IrSimpleFunctionSymbol
declarations += irFunction.withFunction {
overriddenSymbols = listOf(overriddenSymbol)
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.visibility != Visibilities.PRIVATE) {
// Trivial fake override case
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction(
session, originalFunction, functionSymbol
)
val fakeOverrideFunction = fakeOverrideSymbol.fir
val irFunction = declarationStorage.getIrFunction(
fakeOverrideFunction, declarationStorage.findIrParent(originalFunction),
origin = origin, shouldLeaveScope = true
)
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(functionSymbol) as IrSimpleFunctionSymbol
declarations += irFunction.withFunction {
overriddenSymbols = listOf(overriddenSymbol)
}
}
}
}
useSiteMemberScope.processPropertiesByName(name) { propertySymbol ->
if (propertySymbol is FirPropertySymbol) {
val originalProperty = propertySymbol.fir
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
if (propertySymbol.isFakeOverride) {
// Substitution case
val baseSymbol = propertySymbol.deepestOverriddenSymbol() as FirPropertySymbol
val irProperty = declarationStorage.getIrProperty(
originalProperty, irParent = this, origin = origin
)
declarations += irProperty.withProperty {
setOverriddenSymbolsForAccessors(originalProperty, firOverriddenSymbol = baseSymbol)
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.visibility != Visibilities.PRIVATE) {
// Trivial fake override case
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideProperty(
session, originalProperty, propertySymbol, derivedClassId = klass.symbol.classId
)
val fakeOverrideProperty = fakeOverrideSymbol.fir
val irProperty = declarationStorage.getIrProperty(
fakeOverrideProperty, irParent = this, origin = origin
)
declarations += irProperty.withProperty {
setOverriddenSymbolsForAccessors(fakeOverrideProperty, firOverriddenSymbol = propertySymbol)
}
}
}
}
}
}
}
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolved
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol
import org.jetbrains.kotlin.fir.resolve.transformers.IntegerLiteralTypeApproximationTransformer
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
@@ -58,7 +57,7 @@ class Fir2IrVisitor(
private val symbolTable: SymbolTable,
private val sourceManager: PsiSourceManager,
override val irBuiltIns: IrBuiltIns,
private val fakeOverrideMode: FakeOverrideMode
fakeOverrideMode: FakeOverrideMode
) : FirDefaultVisitor<IrElement, Any?>(), IrGeneratorContextInterface {
companion object {
private val NEGATED_OPERATIONS: Set<FirOperation> = EnumSet.of(FirOperation.NOT_EQ, FirOperation.NOT_IDENTITY)
@@ -83,6 +82,8 @@ class Fir2IrVisitor(
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
private val fakeOverrideGenerator = Fir2IrFakeOverrideGenerator(session, declarationStorage, conversionScope, fakeOverrideMode)
override fun visitElement(element: FirElement, data: Any?): IrElement {
TODO("Should not be here: ${element.render()}")
}
@@ -125,75 +126,6 @@ class Fir2IrVisitor(
private fun FirClass<*>.getPrimaryConstructorIfAny(): FirConstructor? =
declarations.filterIsInstance<FirConstructor>().firstOrNull()?.takeIf { it.isPrimary }
private fun IrClass.addFakeOverrides(klass: FirClass<*>, processedCallableNames: MutableList<Name>) {
if (fakeOverrideMode == FakeOverrideMode.NONE) return
val superTypesCallableNames = klass.collectCallableNamesFromSupertypes(session)
val useSiteMemberScope = (klass as? FirRegularClass)?.buildUseSiteMemberScope(session, ScopeSession()) ?: return
for (name in superTypesCallableNames) {
if (name in processedCallableNames) continue
processedCallableNames += name
useSiteMemberScope.processFunctionsByName(name) { functionSymbol ->
if (functionSymbol is FirNamedFunctionSymbol) {
val originalFunction = functionSymbol.fir
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
if (functionSymbol.isFakeOverride) {
// Substitution case
val irFunction = declarationStorage.getIrFunction(
originalFunction, declarationStorage.findIrParent(originalFunction), origin = origin
)
val baseSymbol = functionSymbol.overriddenSymbol
// In fake overrides, parent logic is a bit specific, because
// parent of *original* function (base class) is used for dispatch receiver,
// but fake override itself uses parent from its containing (derived) class
declarations += conversionScope.withFunction(applyParentFromStackTo(irFunction)) {
setFunctionContent(irFunction.descriptor, originalFunction, firOverriddenSymbol = baseSymbol)
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalFunction.visibility != Visibilities.PRIVATE) {
// Trivial fake override case
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideFunction(session, originalFunction, functionSymbol)
val fakeOverrideFunction = fakeOverrideSymbol.fir
val irFunction = declarationStorage.getIrFunction(
fakeOverrideFunction, declarationStorage.findIrParent(originalFunction), origin = origin
)
declarations += conversionScope.withFunction(applyParentFromStackTo(irFunction)) {
setFunctionContent(irFunction.descriptor, fakeOverrideFunction, firOverriddenSymbol = functionSymbol)
}
}
}
}
useSiteMemberScope.processPropertiesByName(name) { propertySymbol ->
if (propertySymbol is FirPropertySymbol) {
val originalProperty = propertySymbol.fir
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
if (propertySymbol.isFakeOverride) {
// Substitution case
val irProperty = declarationStorage.getIrProperty(
originalProperty, declarationStorage.findIrParent(originalProperty), origin = origin
)
val baseSymbol = propertySymbol.overriddenSymbol
declarations += conversionScope.withProperty(applyParentFromStackTo(irProperty)) {
setPropertyContent(irProperty.descriptor, originalProperty, firOverriddenSymbol = baseSymbol)
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION && originalProperty.visibility != Visibilities.PRIVATE) {
// Trivial fake override case
val fakeOverrideSymbol =
FirClassSubstitutionScope.createFakeOverrideProperty(session, originalProperty, propertySymbol)
val fakeOverrideProperty = fakeOverrideSymbol.fir
val irProperty = declarationStorage.getIrProperty(
fakeOverrideProperty, declarationStorage.findIrParent(originalProperty), origin = origin
)
declarations += conversionScope.withProperty(applyParentFromStackTo(irProperty)) {
setPropertyContent(irProperty.descriptor, fakeOverrideProperty, firOverriddenSymbol = propertySymbol)
}
}
}
}
}
}
private fun IrClass.setClassContent(klass: FirClass<*>) {
declarationStorage.enterScope(descriptor)
conversionScope.withClass(this) {
@@ -213,7 +145,7 @@ class Fir2IrVisitor(
}
}
}
addFakeOverrides(klass, processedCallableNames)
with(fakeOverrideGenerator) { addFakeOverrides(klass, processedCallableNames) }
annotations = klass.annotations.mapNotNull {
it.accept(this@Fir2IrVisitor, null) as? IrConstructorCall
}
@@ -250,31 +182,9 @@ class Fir2IrVisitor(
}.also { descriptor.bind(it) }
}
private fun <T : IrFunction> T.setFunctionContent(
descriptor: FunctionDescriptor,
firFunction: FirFunction<*>?,
firOverriddenSymbol: FirNamedFunctionSymbol? = null
): T {
private fun <T : IrFunction> T.setFunctionContent(descriptor: FunctionDescriptor, firFunction: FirFunction<*>?): T {
conversionScope.withParent(this) {
val firFunctionSymbol = (firFunction as? FirSimpleFunction)?.symbol
val lastClass = conversionScope.lastClass()
val containingClass = if (firOverriddenSymbol == null || firFunctionSymbol == null) {
lastClass
} else {
val callableId = firFunctionSymbol.deepestOverriddenSymbol().callableId
val ownerClassId = callableId.classId
if (ownerClassId == null) {
lastClass
} else {
val classLikeSymbol = session.firSymbolProvider.getClassLikeSymbolByFqName(ownerClassId)
if (classLikeSymbol !is FirClassSymbol) {
lastClass
} else {
val firClass = classLikeSymbol.fir as FirClass<*>
declarationStorage.getIrClass(firClass, setParentAndContent = false)
}
}
}
val containingClass = conversionScope.lastClass()
if (firFunction !is FirConstructor && firFunction !is FirAnonymousFunction && containingClass != null) {
addDispatchReceiverParameter(containingClass)
}
@@ -283,12 +193,6 @@ class Fir2IrVisitor(
valueParameter.setDefaultValue(firValueParameter)
}
}
if (firOverriddenSymbol != null && this is IrSimpleFunction && firFunctionSymbol != null) {
val overriddenSymbol = declarationStorage.getIrFunctionSymbol(firOverriddenSymbol)
if (overriddenSymbol is IrSimpleFunctionSymbol) {
overriddenSymbols = listOf(overriddenSymbol)
}
}
var body = firFunction?.body?.convertToIrBlockBody()
if (firFunction is FirConstructor && this is IrConstructor && !parentAsClass.isAnnotationClass) {
if (body == null) {
@@ -456,11 +360,7 @@ class Fir2IrVisitor(
}
}
private fun IrProperty.setPropertyContent(
descriptor: PropertyDescriptor,
property: FirProperty,
firOverriddenSymbol: FirPropertySymbol? = null
): IrProperty {
private fun IrProperty.setPropertyContent(descriptor: PropertyDescriptor, property: FirProperty): IrProperty {
declarationStorage.enterScope(descriptor)
val initializer = property.initializer
val delegate = property.delegate
@@ -482,28 +382,14 @@ class Fir2IrVisitor(
Visibilities.PRIVATE, Name.identifier("${property.name}\$delegate"), true, delegate
)
}
val backingField = backingField
if (firOverriddenSymbol != null && backingField != null) {
val overriddenSymbol = declarationStorage.getIrPropertyOrFieldSymbol(firOverriddenSymbol.fir.backingFieldSymbol)
if (overriddenSymbol is IrFieldSymbol) {
backingField.overriddenSymbols += overriddenSymbol
}
}
}
val overriddenProperty = firOverriddenSymbol?.let { declarationStorage.getIrPropertyOrFieldSymbol(it) } as? IrPropertySymbol
getter?.setPropertyAccessorContent(
property.getter, this, propertyType, property.getter is FirDefaultPropertyGetter, property.getter == null
property.getter, this, propertyType, property.getter is FirDefaultPropertyGetter
)
getter?.apply {
overriddenProperty?.owner?.getter?.symbol?.let { overriddenSymbols = listOf(it) }
}
if (property.isVar) {
setter?.setPropertyAccessorContent(
property.setter, this, propertyType, property.setter is FirDefaultPropertySetter, property.setter == null
property.setter, this, propertyType, property.setter is FirDefaultPropertySetter
)
setter?.apply {
overriddenProperty?.owner?.setter?.symbol?.let { overriddenSymbols = listOf(it) }
}
}
annotations = property.annotations.mapNotNull {
it.accept(this@Fir2IrVisitor, null) as? IrConstructorCall
@@ -532,8 +418,7 @@ class Fir2IrVisitor(
propertyAccessor: FirPropertyAccessor?,
correspondingProperty: IrProperty,
propertyType: IrType,
isDefault: Boolean,
isFakeOverride: Boolean
isDefault: Boolean
) {
conversionScope.withFunction(this) {
if (propertyAccessor != null) {
@@ -543,13 +428,13 @@ class Fir2IrVisitor(
}
applyParentFromStackTo(this)
setFunctionContent(descriptor, propertyAccessor)
if (isDefault || isFakeOverride) {
if (isDefault) {
conversionScope.withParent(this) {
declarationStorage.enterScope(descriptor)
val backingField = correspondingProperty.backingField
val fieldSymbol = symbolTable.referenceField(correspondingProperty.descriptor)
val declaration = this
if (!isFakeOverride && backingField != null) {
if (backingField != null) {
body = IrBlockBodyImpl(
startOffset, endOffset,
listOf(
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
var result = "Fail"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A {
fun foo(x: Int, y: Int = x + 20, z: Int = y * 2) = z
}
@@ -5,18 +5,15 @@ FILE fqName:<root> fileName:/fakeOverridesForJavaStaticMembers.kt
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in a.Base'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test modality:FINAL visibility:public superTypes:[a.Base]'
FUN FAKE_OVERRIDE name:publicStaticMethod visibility:public modality:OPEN <> ($this:a.Base) returnType:kotlin.Unit [fake_override]
FUN FAKE_OVERRIDE name:publicStaticMethod visibility:public modality:OPEN <> () returnType:kotlin.Unit [fake_override]
overridden:
public open fun publicStaticMethod (): kotlin.Unit declared in a.Base
$this: VALUE_PARAMETER name:<this> type:a.Base
FUN FAKE_OVERRIDE name:protectedStaticMethod visibility:protected/*protected static*/ modality:OPEN <> ($this:a.Base) returnType:kotlin.Unit [fake_override]
FUN FAKE_OVERRIDE name:protectedStaticMethod visibility:protected/*protected static*/ modality:OPEN <> () returnType:kotlin.Unit [fake_override]
overridden:
protected/*protected static*/ open fun protectedStaticMethod (): kotlin.Unit declared in a.Base
$this: VALUE_PARAMETER name:<this> type:a.Base
FUN FAKE_OVERRIDE name:packagePrivateStaticMethod visibility:public/*package*/ modality:OPEN <> ($this:a.Base) returnType:kotlin.Unit [fake_override]
FUN FAKE_OVERRIDE name:packagePrivateStaticMethod visibility:public/*package*/ modality:OPEN <> () returnType:kotlin.Unit [fake_override]
overridden:
public/*package*/ open fun packagePrivateStaticMethod (): kotlin.Unit declared in a.Base
$this: VALUE_PARAMETER name:<this> type:a.Base
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
+6 -6
View File
@@ -175,22 +175,22 @@ FILE fqName:<root> fileName:/kt30020.kt
VALUE_PARAMETER name:toIndex index:1 type:kotlin.Int
FUN FAKE_OVERRIDE name:contains visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<E of kotlin.collections.List>, element:kotlin.Int) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public abstract fun contains (element: E of kotlin.collections.MutableList): kotlin.Boolean [operator] declared in kotlin.collections.MutableList
public abstract fun contains (element: E of kotlin.collections.List): kotlin.Boolean [operator] declared in kotlin.collections.List
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List<E of kotlin.collections.List>
VALUE_PARAMETER name:element index:0 type:kotlin.Int
FUN FAKE_OVERRIDE name:containsAll visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<E of kotlin.collections.List>, elements:kotlin.collections.Collection<kotlin.Int>) returnType:kotlin.Boolean [fake_override]
overridden:
public abstract fun containsAll (elements: kotlin.collections.Collection<E of kotlin.collections.MutableList>): kotlin.Boolean declared in kotlin.collections.MutableList
public abstract fun containsAll (elements: kotlin.collections.Collection<E of kotlin.collections.List>): kotlin.Boolean declared in kotlin.collections.List
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List<E of kotlin.collections.List>
VALUE_PARAMETER name:elements index:0 type:kotlin.collections.Collection<kotlin.Int>
FUN FAKE_OVERRIDE name:get visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<E of kotlin.collections.List>, index:kotlin.Int) returnType:kotlin.Int [fake_override,operator]
overridden:
public abstract fun get (index: kotlin.Int): E of kotlin.collections.MutableList [operator] declared in kotlin.collections.MutableList
public abstract fun get (index: kotlin.Int): E of kotlin.collections.List [operator] declared in kotlin.collections.List
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List<E of kotlin.collections.List>
VALUE_PARAMETER name:index index:0 type:kotlin.Int
FUN FAKE_OVERRIDE name:indexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<E of kotlin.collections.List>, element:kotlin.Int) returnType:kotlin.Int [fake_override]
overridden:
public abstract fun indexOf (element: E of kotlin.collections.MutableList): kotlin.Int declared in kotlin.collections.MutableList
public abstract fun indexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List<E of kotlin.collections.List>
VALUE_PARAMETER name:element index:0 type:kotlin.Int
FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<E of kotlin.collections.List>) returnType:kotlin.Boolean [fake_override]
@@ -199,11 +199,11 @@ FILE fqName:<root> fileName:/kt30020.kt
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List<E of kotlin.collections.List>
FUN FAKE_OVERRIDE name:iterator visibility:public modality:ABSTRACT <> ($this:kotlin.collections.MutableCollection<E of kotlin.collections.MutableCollection>) returnType:kotlin.collections.MutableIterator<kotlin.Int> [fake_override,operator]
overridden:
public abstract fun iterator (): kotlin.collections.MutableIterator<E of kotlin.collections.MutableList> [operator] declared in kotlin.collections.MutableList
public abstract fun iterator (): kotlin.collections.MutableIterator<E of kotlin.collections.MutableCollection> [operator] declared in kotlin.collections.MutableCollection
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.MutableCollection<E of kotlin.collections.MutableCollection>
FUN FAKE_OVERRIDE name:lastIndexOf visibility:public modality:ABSTRACT <> ($this:kotlin.collections.List<E of kotlin.collections.List>, element:kotlin.Int) returnType:kotlin.Int [fake_override]
overridden:
public abstract fun lastIndexOf (element: E of kotlin.collections.MutableList): kotlin.Int declared in kotlin.collections.MutableList
public abstract fun lastIndexOf (element: E of kotlin.collections.List): kotlin.Int declared in kotlin.collections.List
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.List<E of kotlin.collections.List>
VALUE_PARAMETER name:element index:0 type:kotlin.Int
PROPERTY FAKE_OVERRIDE name:size visibility:public modality:ABSTRACT [fake_override,val]