[IR] Implement IR actualizer and use it for K2 test and CLI scenario

Implement calculateExpectActualMap for Fir2IrComponents

^KT-51753 Fixed
This commit is contained in:
Ivan Kochurkin
2022-11-18 19:59:14 +01:00
committed by Space Team
parent 15ad9d134c
commit 8936220876
38 changed files with 1241 additions and 27 deletions
@@ -0,0 +1,232 @@
/*
* Copyright 2010-2023 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.backend.common.actualizer
import org.jetbrains.kotlin.backend.common.ir.isProperExpect
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.FqName
internal class ExpectActualCollector(private val mainFragment: IrModuleFragment, private val dependentFragments: List<IrModuleFragment>) {
fun collect(): Map<IrSymbol, IrSymbol> {
val result = mutableMapOf<IrSymbol, IrSymbol>()
// Collect and link classifiers at first to make it possible to expand type aliases on the callables linking
val (allActualDeclarations, typeAliasMap) = result.appendExpectActualClassifiersMap()
result.appendExpectActualCallablesMap(allActualDeclarations, typeAliasMap, dependentFragments)
return result
}
private fun MutableMap<IrSymbol, IrSymbol>.appendExpectActualClassifiersMap(): Pair<Set<IrDeclaration>, Map<FqName, FqName>> {
val actualClassifiers = mutableMapOf<FqName, IrSymbol>()
// There is no list for builtins declarations, that's why they are being collected from typealiases
val allActualDeclarations = mutableSetOf<IrDeclaration>()
val typeAliasMap = mutableMapOf<FqName, FqName>() // It's used to link members from expect class that have typealias actual
ActualClassifiersCollector(actualClassifiers, allActualDeclarations, typeAliasMap).visitModuleFragment(mainFragment)
val linkCollector = ClassifiersLinkCollector(this, actualClassifiers)
dependentFragments.forEach { linkCollector.visitModuleFragment(it) }
return allActualDeclarations to typeAliasMap
}
class ActualClassifiersCollector(
private val actualClassifiers: MutableMap<FqName, IrSymbol>,
private val allActualClassifiers: MutableSet<IrDeclaration>,
private val typeAliasMap: MutableMap<FqName, FqName>
) : IrElementVisitorVoid {
override fun visitTypeAlias(declaration: IrTypeAlias) {
if (declaration.isActual) {
val expandedTypeSymbol = declaration.expandedType.classifierOrFail
actualClassifiers[declaration.kotlinFqName] = expandedTypeSymbol
if (expandedTypeSymbol is IrClassSymbol) {
allActualClassifiers.add(expandedTypeSymbol.owner)
typeAliasMap[declaration.kotlinFqName] = expandedTypeSymbol.owner.kotlinFqName
}
}
visitElement(declaration)
}
override fun visitClass(declaration: IrClass) {
if (!declaration.isExpect) {
actualClassifiers[declaration.kotlinFqName] = declaration.symbol
}
visitDeclaration(declaration)
}
override fun visitEnumEntry(declaration: IrEnumEntry) {
if (!declaration.isProperExpect) {
actualClassifiers[FqName.fromSegments(
listOf(
declaration.parent.kotlinFqName.asString(),
declaration.name.asString()
)
)] = declaration.symbol
}
visitDeclaration(declaration)
}
override fun visitTypeParameter(declaration: IrTypeParameter) {
if (!declaration.isProperExpect) {
actualClassifiers[FqName.fromSegments(
listOf(declaration.parent.kotlinFqName.asString(), declaration.name.asString())
)] = declaration.symbol
}
visitDeclaration(declaration)
}
override fun visitDeclaration(declaration: IrDeclarationBase) {
if (!declaration.isProperExpect) {
allActualClassifiers.add(declaration)
}
visitElement(declaration)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
}
class ClassifiersLinkCollector(
private val expectActualMap: MutableMap<IrSymbol, IrSymbol>,
private val actualClassifiers: Map<FqName, IrSymbol>
) : IrElementVisitorVoid {
private fun addLinkOrReportMissing(expectElement: IrSymbolOwner, actualTypeId: FqName) {
val actualClassifier = actualClassifiers[actualTypeId]
if (actualClassifier != null) {
expectActualMap[expectElement.symbol] = actualClassifier
} else {
reportMissingActual(expectElement)
}
}
override fun visitClass(declaration: IrClass) {
if (declaration.isExpect) {
addLinkOrReportMissing(declaration, declaration.kotlinFqName)
}
visitElement(declaration)
}
override fun visitEnumEntry(declaration: IrEnumEntry) {
if (declaration.isProperExpect) {
addLinkOrReportMissing(
declaration, FqName.fromSegments(listOf(declaration.parent.kotlinFqName.asString(), declaration.name.asString()))
)
}
visitElement(declaration)
}
override fun visitTypeParameter(declaration: IrTypeParameter) {
if (declaration.isProperExpect) {
addLinkOrReportMissing(
declaration,
FqName.fromSegments(listOf(declaration.parent.kotlinFqName.asString(), declaration.name.asString()))
)
}
visitElement(declaration)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
}
private fun MutableMap<IrSymbol, IrSymbol>.appendExpectActualCallablesMap(
allActualDeclarations: Set<IrDeclaration>,
typeAliasMap: Map<FqName, FqName>,
dependentFragments: List<IrModuleFragment>
) {
val actualFunctions = mutableMapOf<CallableId, MutableList<IrFunction>>()
val actualProperties = mutableMapOf<CallableId, IrProperty>()
collectActualCallables(actualFunctions, actualProperties, allActualDeclarations)
val collector = CallablesLinkCollector(this, actualFunctions, actualProperties, typeAliasMap)
dependentFragments.forEach { collector.visitModuleFragment(it) }
}
private fun collectActualCallables(
actualFunctions: MutableMap<CallableId, MutableList<IrFunction>>,
actualProperties: MutableMap<CallableId, IrProperty>,
allActualDeclarations: Set<IrDeclaration>
) {
fun collectActualsCallables(declaration: IrDeclaration) {
when (declaration) {
is IrFunction -> {
actualFunctions.getOrPut(CallableId(declaration.parent.kotlinFqName, declaration.name)) {
mutableListOf()
}.add(declaration)
}
is IrProperty -> {
actualProperties.getOrPut(CallableId(declaration.parent.kotlinFqName, declaration.name)) {
declaration
}
}
is IrClass -> {
for (member in declaration.declarations) {
collectActualsCallables(member)
}
}
}
}
for (actualDeclaration in allActualDeclarations) {
collectActualsCallables(actualDeclaration)
}
}
class CallablesLinkCollector(
private val expectActualMap: MutableMap<IrSymbol, IrSymbol>,
private val actualFunctions: MutableMap<CallableId, MutableList<IrFunction>>,
private val actualProperties: MutableMap<CallableId, IrProperty>,
private val typeAliasMap: Map<FqName, FqName>
) : IrElementVisitorVoid {
private fun actualizeCallable(declaration: IrDeclarationWithName): CallableId {
val fullName = declaration.parent.kotlinFqName
return CallableId(typeAliasMap[fullName] ?: fullName, declaration.name)
}
override fun visitFunction(declaration: IrFunction) {
if (!declaration.isExpect) return
val functions = actualFunctions[actualizeCallable(declaration)]
var isActualFunctionFound = false
if (functions != null) {
for (actualFunction in functions) {
if (checkParameters(declaration, actualFunction, expectActualMap)) {
expectActualMap[declaration.symbol] = actualFunction.symbol
isActualFunctionFound = true
break
}
}
}
if (!isActualFunctionFound) {
reportMissingActual(declaration)
}
}
override fun visitProperty(declaration: IrProperty) {
if (!declaration.isExpect) return
val properties = actualProperties[actualizeCallable(declaration)]
if (properties != null) {
expectActualMap[declaration.symbol] = properties.symbol
declaration.getter?.symbol?.let { expectActualMap[it] = properties.getter!!.symbol }
declaration.setter?.symbol?.let { expectActualMap[it] = properties.setter!!.symbol }
} else {
reportMissingActual(declaration)
}
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
}
}
@@ -0,0 +1,161 @@
/*
* Copyright 2010-2023 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.backend.common.actualizer
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
import org.jetbrains.kotlin.ir.util.SymbolRemapper
import org.jetbrains.kotlin.ir.util.SymbolRenamer
class ExpectActualLinker(private val expectActualMap: Map<IrSymbol, IrSymbol>) {
private val symbolRemapper = object : SymbolRemapper {
override fun getDeclaredClass(symbol: IrClassSymbol) = symbol
override fun getDeclaredScript(symbol: IrScriptSymbol) = symbol
override fun getDeclaredFunction(symbol: IrSimpleFunctionSymbol) = symbol
override fun getDeclaredProperty(symbol: IrPropertySymbol) = symbol
override fun getDeclaredField(symbol: IrFieldSymbol) = symbol
override fun getDeclaredFile(symbol: IrFileSymbol) = symbol
override fun getDeclaredConstructor(symbol: IrConstructorSymbol) = symbol
override fun getDeclaredEnumEntry(symbol: IrEnumEntrySymbol) = symbol
override fun getDeclaredExternalPackageFragment(symbol: IrExternalPackageFragmentSymbol) = symbol
override fun getDeclaredVariable(symbol: IrVariableSymbol) = symbol
override fun getDeclaredLocalDelegatedProperty(symbol: IrLocalDelegatedPropertySymbol) = symbol
override fun getDeclaredTypeParameter(symbol: IrTypeParameterSymbol) = symbol
override fun getDeclaredValueParameter(symbol: IrValueParameterSymbol) = symbol
override fun getDeclaredTypeAlias(symbol: IrTypeAliasSymbol) = symbol
override fun getReferencedClass(symbol: IrClassSymbol) = symbol.actualizeSymbol()
override fun getReferencedScript(symbol: IrScriptSymbol) = symbol.actualizeSymbol()
override fun getReferencedClassOrNull(symbol: IrClassSymbol?) = symbol?.actualizeSymbol()
override fun getReferencedEnumEntry(symbol: IrEnumEntrySymbol) = symbol.actualizeSymbol()
override fun getReferencedVariable(symbol: IrVariableSymbol) = symbol.actualizeSymbol()
override fun getReferencedLocalDelegatedProperty(symbol: IrLocalDelegatedPropertySymbol) = symbol.actualizeSymbol()
override fun getReferencedField(symbol: IrFieldSymbol) = symbol.actualizeSymbol()
override fun getReferencedConstructor(symbol: IrConstructorSymbol) = symbol.actualizeSymbol()
override fun getReferencedValue(symbol: IrValueSymbol) = symbol.actualizeSymbol()
override fun getReferencedFunction(symbol: IrFunctionSymbol) = symbol.actualizeSymbol()
override fun getReferencedProperty(symbol: IrPropertySymbol) = symbol.actualizeSymbol()
override fun getReferencedSimpleFunction(symbol: IrSimpleFunctionSymbol) = symbol.actualizeSymbol()
override fun getReferencedReturnableBlock(symbol: IrReturnableBlockSymbol) = symbol.actualizeSymbol()
override fun getReferencedClassifier(symbol: IrClassifierSymbol) = symbol.actualizeSymbol()
override fun getReferencedTypeAlias(symbol: IrTypeAliasSymbol) = symbol.actualizeSymbol()
private inline fun <reified S : IrSymbol> S.actualizeSymbol(): S = (expectActualMap[this] as? S) ?: this
}
private val typeRemapper = DeepCopyTypeRemapper(symbolRemapper)
private val actualizer = object : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper, SymbolRenamer.DEFAULT) {
override fun visitModuleFragment(declaration: IrModuleFragment) =
declaration.also { it.transformChildren(this, null) }
override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment) =
declaration.also { it.transformChildren(this, null) }
override fun visitFile(declaration: IrFile) =
declaration.also { it.transformChildren(this, null) }
override fun visitScript(declaration: IrScript) =
declaration.also {
it.baseClass = it.baseClass?.remapType()
it.transformChildren(this, null)
}
override fun visitClass(declaration: IrClass) =
declaration.also {
it.superTypes = it.superTypes.map { superType -> superType.remapType() }
it.transformChildren(this, null)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction) = visitFunction(declaration) as IrSimpleFunction
override fun visitConstructor(declaration: IrConstructor) = visitFunction(declaration) as IrConstructor
override fun visitFunction(declaration: IrFunction) =
declaration.also {
it.returnType = it.returnType.remapType()
it.transformChildren(this, null)
}
override fun visitProperty(declaration: IrProperty) =
declaration.also { it.transformChildren(this, null) }
override fun visitField(declaration: IrField) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitEnumEntry(declaration: IrEnumEntry) =
declaration.also { it.transformChildren(this, null) }
override fun visitTypeParameter(declaration: IrTypeParameter) =
declaration.also {
it.superTypes = it.superTypes.map { superType -> superType.remapType() }
it.transformChildren(this, null)
}
override fun visitValueParameter(declaration: IrValueParameter) =
declaration.also {
it.type = it.type.remapType()
it.varargElementType = it.varargElementType?.remapType()
it.transformChildren(this, null)
}
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) =
declaration.also { it.transformChildren(this, null) }
override fun visitVariable(declaration: IrVariable) =
declaration.also {
it.type = it.type.remapType()
it.transformChildren(this, null)
}
override fun visitTypeAlias(declaration: IrTypeAlias) =
declaration.also {
it.expandedType = it.expandedType.remapType()
it.transformChildren(this, null)
}
}
fun actualize(irElement: IrElement) = irElement.transform(actualizer, null)
}
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2023 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.backend.common.actualizer
import org.jetbrains.kotlin.backend.common.ir.isProperExpect
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrSymbol
object IrActualizer {
fun actualize(mainFragment: IrModuleFragment, dependentFragments: List<IrModuleFragment>) {
val expectActualMap = ExpectActualCollector(mainFragment, dependentFragments).collect()
removeExpectDeclaration(dependentFragments) // TODO: consider removing this call. See ExpectDeclarationRemover.kt
addMissingFakeOverrides(expectActualMap, dependentFragments)
linkExpectToActual(expectActualMap, dependentFragments)
mergeIrFragments(mainFragment, dependentFragments)
}
private fun removeExpectDeclaration(dependentFragments: List<IrModuleFragment>) {
for (fragment in dependentFragments) {
for (file in fragment.files) {
file.declarations.removeAll { it.isProperExpect }
}
}
}
private fun addMissingFakeOverrides(expectActualMap: Map<IrSymbol, IrSymbol>, dependentFragments: List<IrModuleFragment>) {
MissingFakeOverridesAdder(expectActualMap).apply { dependentFragments.forEach { visitModuleFragment(it) } }
}
private fun linkExpectToActual(expectActualMap: Map<IrSymbol, IrSymbol>, dependentFragments: List<IrModuleFragment>) {
ExpectActualLinker(expectActualMap).apply { dependentFragments.forEach { actualize(it) } }
}
private fun mergeIrFragments(mainFragment: IrModuleFragment, dependentFragments: List<IrModuleFragment>) {
mainFragment.files.addAll(dependentFragments.flatMap { it.files })
}
}
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2023 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.backend.common.actualizer
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.render
fun checkParameters(
expectFunction: IrFunction,
actualFunction: IrFunction,
expectActualTypesMap: Map<IrSymbol, IrSymbol>
): Boolean {
if (expectFunction.valueParameters.size != actualFunction.valueParameters.size) return false
for ((expectParameter, actualParameter) in expectFunction.valueParameters.zip(actualFunction.valueParameters)) {
val expectParameterTypeSymbol = expectParameter.type.classifierOrFail
val actualizedParameterTypeSymbol = expectActualTypesMap[expectParameterTypeSymbol] ?: expectParameterTypeSymbol
if (actualizedParameterTypeSymbol != actualParameter.type.classifierOrFail) {
return false
}
}
return true
}
fun reportMissingActual(irElement: IrElement) {
// TODO: set up diagnostics reporting
throw AssertionError("Missing actual for ${irElement.render()}")
}
fun reportManyInterfacesMembersNotImplemented(declaration: IrClass, actualMember: IrDeclarationWithName) {
// TODO: set up diagnostics reporting
throw AssertionError("${declaration.name} must override ${actualMember.name} because it inherits multiple interface methods of it")
}
@@ -0,0 +1,148 @@
/*
* Copyright 2010-2023 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.backend.common.actualizer
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
class MissingFakeOverridesAdder(private val expectActualMap: Map<IrSymbol, IrSymbol>) : IrElementVisitorVoid {
override fun visitClass(declaration: IrClass) {
if (!declaration.isExpect) {
processSupertypes(declaration, expectActualMap)
}
visitElement(declaration)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
}
private fun processSupertypes(declaration: IrClass, expectActualMap: Map<IrSymbol, IrSymbol>) {
val members by lazy(LazyThreadSafetyMode.NONE) {
declaration.declarations.filter { !it.isBuiltinMember() }.filterIsInstance<IrDeclarationWithName>()
.groupBy { it.name }
}
for (superType in declaration.superTypes) {
val actualClass = expectActualMap[superType.classifierOrFail]?.owner as? IrClass ?: continue
for (actualMember in actualClass.declarations) {
if (actualMember.isBuiltinMember()) continue
when (actualMember) {
is IrFunctionImpl -> {
val existingMembers = members[actualMember.name]
var isActualFunctionFound = false
if (existingMembers != null) {
for (existingMember in existingMembers) {
if (existingMember is IrFunction) {
if (checkParameters(existingMember, actualMember, expectActualMap)) {
isActualFunctionFound = true
break
}
}
}
}
if (isActualFunctionFound) {
reportManyInterfacesMembersNotImplemented(declaration, actualMember)
continue
}
declaration.declarations.add(createFakeOverrideFunction(actualMember, declaration))
}
is IrPropertyImpl -> {
if (members[actualMember.name] != null) {
reportManyInterfacesMembersNotImplemented(declaration, actualMember)
continue
}
declaration.declarations.add(createFakeOverrideProperty(actualMember, declaration))
}
}
}
}
}
private fun IrDeclaration.isBuiltinMember(): Boolean {
if (this !is IrFunction) return false
return this is IrConstructor || dispatchReceiverParameter?.type?.isAny() == true
}
private fun createFakeOverrideProperty(actualMember: IrPropertyImpl, declaration: IrClass) =
IrPropertyImpl(
actualMember.startOffset,
actualMember.endOffset,
IrDeclarationOrigin.FAKE_OVERRIDE,
IrPropertySymbolImpl(),
actualMember.name,
actualMember.visibility,
actualMember.modality,
actualMember.isVar,
actualMember.isConst,
actualMember.isLateinit,
actualMember.isDelegated,
isExternal = actualMember.isExternal
).also {
it.parent = declaration
it.annotations = actualMember.annotations
it.backingField = actualMember.backingField
it.getter = (actualMember.getter as? IrFunctionImpl)?.let { getter ->
createFakeOverrideFunction(getter, declaration, it.symbol)
}
it.setter = (actualMember.setter as? IrFunctionImpl)?.let { setter ->
createFakeOverrideFunction(setter, declaration, it.symbol)
}
it.overriddenSymbols = listOf(actualMember.symbol)
it.metadata = actualMember.metadata
it.attributeOwnerId = it
}
private fun createFakeOverrideFunction(
actualFunction: IrFunctionImpl,
parent: IrDeclarationParent,
correspondingPropertySymbol: IrPropertySymbol? = null
) =
IrFunctionImpl(
actualFunction.startOffset,
actualFunction.endOffset,
IrDeclarationOrigin.FAKE_OVERRIDE,
IrSimpleFunctionSymbolImpl(),
actualFunction.name,
actualFunction.visibility,
actualFunction.modality,
actualFunction.returnType,
actualFunction.isInline,
actualFunction.isExternal,
actualFunction.isTailrec,
actualFunction.isSuspend,
actualFunction.isOperator,
actualFunction.isInfix,
isExpect = false
).also {
it.parent = parent
it.annotations = actualFunction.annotations.map { p -> p.deepCopyWithSymbols(it) }
it.typeParameters = actualFunction.typeParameters.map { p -> p.deepCopyWithSymbols(it) }
it.dispatchReceiverParameter = actualFunction.dispatchReceiverParameter?.deepCopyWithSymbols(it)
it.extensionReceiverParameter = actualFunction.extensionReceiverParameter?.deepCopyWithSymbols(it)
it.valueParameters = actualFunction.valueParameters.map { p -> p.deepCopyWithSymbols(it) }
it.contextReceiverParametersCount = actualFunction.contextReceiverParametersCount
it.metadata = actualFunction.metadata
it.overriddenSymbols = listOf(actualFunction.symbol)
it.attributeOwnerId = it
it.correspondingPropertySymbol = correspondingPropertySymbol
}
@@ -15,7 +15,6 @@ val IrDeclaration.isExpect
// The original isExpect represents what user has written.
// This predicate means "there can possibly exist an 'actual' for the given declaration".
// Shouldn't it be incorporated to descriptor -> ir declaration psi2ir translation phase?
@Suppress("unused")
val IrDeclaration.isProperExpect: Boolean
get() = this is IrClass && isExpect ||
this is IrFunction && isExpect ||