[K2, MPP] Fix actualization of fake overrides (fixes a set of bugs in coroutines / ktor)

Split MissingFakeOverridesAdder on FakeOverridesActualizer and ActualFakeOverridesAdder

^KT-57984 Fixed
^KT-58003 Fixed
^KT-58124 Fixed
^KT-57833 Fixed
^KT-58153 Fixed
This commit is contained in:
Ivan Kochurkin
2023-04-11 21:41:36 +02:00
committed by Space Team
parent 58f8e25bfe
commit 432c781ff7
39 changed files with 1581 additions and 182 deletions
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
object CommonBackendErrors {
val NO_ACTUAL_FOR_EXPECT by error2<PsiElement, String, ModuleDescriptor>()
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error2<PsiElement, String, String>()
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error2<PsiElement, String, String>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultCommonBackendErrorMessages)
@@ -37,5 +38,11 @@ object KtDefaultCommonBackendErrorMessages : BaseDiagnosticRendererFactory() {
STRING,
STRING,
)
map.put(
CommonBackendErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED,
"{0} must override {1} because it inherits many implementations of it",
STRING,
STRING,
)
}
}
@@ -0,0 +1,120 @@
/*
* 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.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.backend.common.CommonBackendErrors
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
/**
* It adds fake overrides to non-expect classes inside common or multi-platform module,
* taken from these non-expect classes actualized super classes.
*
* In case when a non-expect class has direct or indirect expect supertypes,
* it may happen that the actual classes for these supertypes contain additional (non-actual) members that don't exist in their expect counterparts.
* We still should have fake overrides generated for these members, but FIR2IR isn't able to see their base members in common or multi-platform module.
* This class is intended to search for such situations and generate such fake overrides.
*/
internal class ActualFakeOverridesAdder(
private val expectActualMap: Map<IrSymbol, IrSymbol>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) : IrElementVisitorVoid {
private val missingActualMembersMap = mutableMapOf<IrClass, MutableMap<String, MutableList<IrDeclaration>>>()
override fun visitClass(declaration: IrClass) {
extractMissingActualMembersFromSupertypes(declaration)
visitElement(declaration)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
private fun extractMissingActualMembersFromSupertypes(klass: IrClass): Map<String, MutableList<IrDeclaration>> {
missingActualMembersMap[klass]?.let { return it }
val missingActualMembers = mutableMapOf<String, MutableList<IrDeclaration>>()
missingActualMembersMap[klass] = missingActualMembers
// New members from supertypes are only relevant for not expect (ordinary) classes
// New members from the current class are only relevant for actualized expect classes
val processedMembers = mutableMapOf<String, MutableList<IrDeclaration>>()
for (superType in klass.superTypes) {
val membersFromSupertype = extractMissingActualMembersFromSupertypes(superType.classifierOrFail.owner as IrClass)
if (!klass.isExpect) {
missingActualMembers.appendMissingMembersToNotExpectClass(klass, membersFromSupertype, processedMembers)
}
}
val actualClass = expectActualMap[klass.symbol]?.owner as? IrClass ?: return missingActualMembers
missingActualMembers.appendMissingMembersFromActualizedExpectClass(klass, actualClass)
return missingActualMembers
}
private fun MutableMap<String, MutableList<IrDeclaration>>.appendMissingMembersToNotExpectClass(
klass: IrClass,
membersFromSupertype: Map<String, MutableList<IrDeclaration>>,
processedMembers: MutableMap<String, MutableList<IrDeclaration>>
) {
for (memberFromSupertype in membersFromSupertype.flatMap { it.value }) {
val newMember = createFakeOverrideMember(listOf(memberFromSupertype), klass)
val name = newMember.getFunctionOrPropertyName()
if (getMatches(name, newMember, expectActualMap).isEmpty()) {
processedMembers.addMember(memberFromSupertype as IrOverridableDeclaration<*>)
addMember(newMember)
klass.addMember(newMember)
} else {
val baseMember = processedMembers.getMatches(name, newMember, expectActualMap).single()
val errorFactory =
if ((baseMember.parent as IrClass).isInterface && (memberFromSupertype.parent as IrClass).isInterface)
CommonBackendErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
else
CommonBackendErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
diagnosticsReporter.at(klass).report(
errorFactory,
klass.name.asString(),
(memberFromSupertype as IrDeclarationWithName).name.asString()
)
}
}
}
private fun MutableMap<String, MutableList<IrDeclaration>>.appendMissingMembersFromActualizedExpectClass(
expectClass: IrClass,
actualClass: IrClass,
) {
val actualWithCorrespondingExpectMembers = hashSetOf<IrSymbol>().apply {
expectClass.declarations.mapNotNullTo(this) { expectActualMap[(it as? IrOverridableDeclaration<*>)?.symbol] }
}
for (actualMember in actualClass.declarations) {
if (actualMember is IrOverridableDeclaration<*> &&
(actualMember as? IrDeclarationWithVisibility)?.visibility != DescriptorVisibilities.PRIVATE &&
!actualWithCorrespondingExpectMembers.contains(actualMember.symbol)
) {
addMember(actualMember)
}
}
}
private fun MutableMap<String, MutableList<IrDeclaration>>.addMember(member: IrOverridableDeclaration<*>) {
getOrPut(member.getFunctionOrPropertyName()) { mutableListOf() }.add(member)
}
private fun IrOverridableDeclaration<*>.getFunctionOrPropertyName(): String {
return (this as IrDeclarationWithName).name.asString() + (if (this is IrSimpleFunction) "()" else "")
}
}
@@ -11,6 +11,7 @@ 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.isFakeOverride
import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -21,12 +22,12 @@ internal class ExpectActualCollector(
private val dependentFragments: List<IrModuleFragment>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) {
fun collect(): Pair<Map<IrSymbol, IrSymbol>, Map<FqName, FqName>> {
fun collect(): MutableMap<IrSymbol, IrSymbol> {
val result = mutableMapOf<IrSymbol, IrSymbol>()
// Collect and link classes at first to make it possible to expand type aliases on the members linking
val (actualMembers, expectActualTypeAliasMap) = result.appendExpectActualClassMap()
result.appendExpectActualMemberMap(actualMembers, expectActualTypeAliasMap)
return result to expectActualTypeAliasMap
return result
}
private fun MutableMap<IrSymbol, IrSymbol>.appendExpectActualClassMap(): Pair<List<IrDeclarationBase>, Map<FqName, FqName>> {
@@ -157,39 +158,37 @@ private class MemberLinksCollector(
if ((declaration.parent as IrClass).isExpect) addLink(declaration)
}
private fun addLink(declaration: IrDeclarationBase) {
val actualMemberMatches = actualMembers.getMatches(declaration, expectActualMap, typeAliasMap)
private fun addLink(expectDeclaration: IrDeclarationBase) {
val actualMemberMatches = actualMembers.getMatches(expectDeclaration, expectActualMap, typeAliasMap)
when {
actualMemberMatches.size == 1 -> {
val actualMember = actualMemberMatches.single()
expectActualMap[declaration.symbol] = actualMember.symbol
if (declaration is IrProperty) {
val actualProperty = actualMember as IrProperty
declaration.getter?.let {
val getter = actualProperty.getter!!
expectActualMap[it.symbol] = getter.symbol
expectActualMap.appendTypeParametersMap(it, getter)
}
declaration.setter?.symbol?.let { expectActualMap[it] = actualProperty.setter!!.symbol }
} else if (declaration is IrFunction) {
expectActualMap.appendTypeParametersMap(declaration, actualMember as IrFunction)
}
expectActualMap.addLink(expectDeclaration, actualMemberMatches.single())
}
actualMemberMatches.size > 1 -> {
// TODO: report AMBIGUOUS_ACTUALS here, see KT-57932
}
!declaration.parent.containsOptionalExpectation() && !(declaration is IrConstructor && declaration.isPrimary) -> {
diagnosticsReporter.reportMissingActual(declaration)
(expectDeclaration.parent as? IrClass)?.isExpect == false && expectDeclaration.isFakeOverride -> {
// Remaining expect fake override members from not expect classes will be actualized in FakeOverridesTransformer
// It occurs in a separated step because they require filled expectActualMap for members from expect classes
}
else -> {
if (shouldReportMissingActual(expectDeclaration)) {
diagnosticsReporter.reportMissingActual(expectDeclaration)
}
}
}
}
private fun shouldReportMissingActual(declaration: IrDeclarationBase): Boolean {
return !declaration.parent.containsOptionalExpectation() && !(declaration is IrConstructor && declaration.isPrimary)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
}
private fun MutableMap<IrSymbol, IrSymbol>.appendTypeParametersMap(
fun MutableMap<IrSymbol, IrSymbol>.appendTypeParametersMap(
expectTypeParametersContainer: IrTypeParametersContainer,
actualTypeParametersContainer: IrTypeParametersContainer
) {
@@ -7,7 +7,11 @@ package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.SymbolRemapper
import org.jetbrains.kotlin.ir.util.SymbolRenamer
import org.jetbrains.kotlin.ir.util.TypeRemapper
import org.jetbrains.kotlin.utils.memoryOptimizedMap
internal class ActualizerSymbolRemapper(private val expectActualMap: Map<IrSymbol, IrSymbol>) : SymbolRemapper {
override fun getDeclaredClass(symbol: IrClassSymbol) = symbol
@@ -71,7 +75,7 @@ internal class ActualizerSymbolRemapper(private val expectActualMap: Map<IrSymbo
private inline fun <reified S : IrSymbol> S.actualizeSymbol(): S = (expectActualMap[this] as? S) ?: this
}
internal open class ActualizerVisitor(symbolRemapper: SymbolRemapper, typeRemapper: TypeRemapper) :
internal open class ActualizerVisitor(private val symbolRemapper: SymbolRemapper, typeRemapper: TypeRemapper) :
DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper, SymbolRenamer.DEFAULT) {
override fun visitModuleFragment(declaration: IrModuleFragment) =
declaration.also { it.transformChildren(this, null) }
@@ -94,7 +98,11 @@ internal open class ActualizerVisitor(symbolRemapper: SymbolRemapper, typeRemapp
it.transformChildren(this, null)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction) = visitFunction(declaration) as IrSimpleFunction
override fun visitSimpleFunction(declaration: IrSimpleFunction) = (visitFunction(declaration) as IrSimpleFunction).also {
it.overriddenSymbols = it.overriddenSymbols.memoryOptimizedMap { symbol ->
symbolRemapper.getReferencedFunction(symbol) as IrSimpleFunctionSymbol
}
}
override fun visitConstructor(declaration: IrConstructor) = visitFunction(declaration) as IrConstructor
@@ -105,7 +113,12 @@ internal open class ActualizerVisitor(symbolRemapper: SymbolRemapper, typeRemapp
}
override fun visitProperty(declaration: IrProperty) =
declaration.also { it.transformChildren(this, null) }
declaration.also {
it.transformChildren(this, null)
it.overriddenSymbols = it.overriddenSymbols.memoryOptimizedMap { symbol ->
symbolRemapper.getReferencedProperty(symbol)
}
}
override fun visitField(declaration: IrField) =
declaration.also {
@@ -0,0 +1,57 @@
/*
* 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.isExpect
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrOverridableDeclaration
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.isFakeOverride
import org.jetbrains.kotlin.ir.util.transformInPlace
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
/**
* It actualizes expect fake overrides in non-expect classes inside common or multi-platform module.
*
* When some non-expect class inside a common or multi-platform module has an expect base class,
* FIR2IR generates expect fake overrides overriding the expect base class members for this non-expect class which is not correct for the backend.
* This Actualizer processes expect overridable declarations in non-expect classes and replaces them with the associated actual overridable
* declarations overriding the actual base class members.The newly created actual fake overrides are stored in expectActualMap.
*/
internal class FakeOverridesActualizer(private val expectActualMap: MutableMap<IrSymbol, IrSymbol>) : IrElementVisitorVoid {
override fun visitClass(declaration: IrClass) {
if (!declaration.isExpect) {
actualizeFakeOverrides(declaration)
}
visitElement(declaration)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
private fun actualizeFakeOverrides(klass: IrClass) {
fun IrDeclaration.actualize(): IrDeclaration {
if (!isExpect) return this
(expectActualMap[symbol]?.owner as? IrDeclaration)?.let { return it }
require(this is IrOverridableDeclaration<*>)
val actualizedOverrides = overriddenSymbols.map { (it.owner as IrDeclaration).actualize() }
val actualFakeOverride = createFakeOverrideMember(actualizedOverrides, parent as IrClass)
expectActualMap.addLink(this as IrDeclarationBase, actualFakeOverride)
return actualFakeOverride
}
klass.declarations.transformInPlace { if (it.isExpect && it.isFakeOverride) it.actualize() else it }
}
}
@@ -23,27 +23,40 @@ object IrActualizer {
): IrActualizedResult {
val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, languageVersionSettings)
val (expectActualMap, expectActualTypeAliasMap) = ExpectActualCollector(
// The ir modules processing is performed phase-to-phase:
// 1. Collect expect-actual links for classes and their members from dependent fragments
val expectActualMap = ExpectActualCollector(
mainFragment,
dependentFragments,
ktDiagnosticReporter
).collect()
// 2. Remove top-only expect declarations since they are not needed anymore and should not be presented in the final IrFragment
// Expect fake-overrides from non-expect classes remain untouched since they will be actualized in the next phase.
// Also, it doesn't remove unactualized expect declarations marked with @OptionalExpectation
val removedExpectDeclarations = removeExpectDeclarations(dependentFragments, expectActualMap)
// 3. Actualize expect fake overrides in non-expect classes inside common or multi-platform module.
// It's probably important to run FakeOverridesActualizer before ActualFakeOverridesAdder
FakeOverridesActualizer(expectActualMap).apply { dependentFragments.forEach { visitModuleFragment(it) } }
// 4. Add fake overrides to non-expect classes inside common or multi-platform module,
// taken from these non-expect classes actualized super classes.
ActualFakeOverridesAdder(
expectActualMap,
ktDiagnosticReporter
).apply { dependentFragments.forEach { visitModuleFragment(it) } }
// 5. Copy and actualize function parameter default values from expect functions
val symbolRemapper = ActualizerSymbolRemapper(expectActualMap)
val typeRemapper = DeepCopyTypeRemapper(symbolRemapper)
FunctionDefaultParametersActualizer(symbolRemapper, typeRemapper, expectActualMap).actualize()
MissingFakeOverridesAdder(
expectActualMap,
expectActualTypeAliasMap,
ktDiagnosticReporter
).apply { dependentFragments.forEach { visitModuleFragment(it) } }
// 6. Actualize expect calls in dependent fragments using info obtained in the previous steps
val actualizerVisitor = ActualizerVisitor(symbolRemapper, typeRemapper)
dependentFragments.forEach { it.transform(actualizerVisitor, null) }
// 7. Merge dependent fragments into the main one
mergeIrFragments(mainFragment, dependentFragments)
return IrActualizedResult(removedExpectDeclarations)
@@ -10,18 +10,20 @@ import org.jetbrains.kotlin.backend.common.CommonBackendErrors
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.ir.util.module
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
import org.jetbrains.kotlin.utils.addToStdlib.runIf
private val FLEXIBLE_NULLABILITY_ANNOTATION_FQ_NAME = StandardClassIds.Annotations.FlexibleNullability.asSingleFqName()
@@ -29,8 +31,15 @@ internal fun Map<String, List<IrDeclaration>>.getMatches(
expectDeclaration: IrDeclaration,
expectActualTypesMap: Map<IrSymbol, IrSymbol>,
expectActualTypeAliasMap: Map<FqName, FqName>
): List<IrDeclaration> =
getMatches(generateIrElementFullNameFromExpect(expectDeclaration, expectActualTypeAliasMap), expectDeclaration, expectActualTypesMap)
internal fun Map<String, List<IrDeclaration>>.getMatches(
mainSignature: String,
expectDeclaration: IrDeclaration,
expectActualTypesMap: Map<IrSymbol, IrSymbol>
): List<IrDeclaration> {
val members = this[generateIrElementFullNameFromExpect(expectDeclaration, expectActualTypeAliasMap)] ?: return emptyList()
val members = this[mainSignature] ?: return emptyList()
return when (expectDeclaration) {
is IrFunction -> members.getMatches(expectDeclaration, expectActualTypesMap) { it as IrFunction }
is IrProperty -> members.getMatches(expectDeclaration, expectActualTypesMap) { (it as IrProperty).getter!! }
@@ -167,6 +176,21 @@ private fun appendElementFullName(
}
}
internal fun MutableMap<IrSymbol, IrSymbol>.addLink(expectMember: IrDeclarationBase, actualMember: IrDeclaration) {
this[expectMember.symbol] = actualMember.symbol
if (expectMember is IrProperty) {
val actualProperty = actualMember as IrProperty
expectMember.getter!!.let {
val getter = actualProperty.getter!!
this[it.symbol] = getter.symbol
this.appendTypeParametersMap(it, getter)
}
expectMember.setter?.symbol?.let { this[it] = actualProperty.setter!!.symbol }
} else if (expectMember is IrFunction) {
this.appendTypeParametersMap(expectMember, actualMember as IrFunction)
}
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportMissingActual(irDeclaration: IrDeclaration) {
at(irDeclaration).report(
@@ -181,3 +205,67 @@ internal fun IrElement.containsOptionalExpectation(): Boolean {
this.kind == ClassKind.ANNOTATION_CLASS &&
this.hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
}
@Suppress("UNCHECKED_CAST")
internal fun createFakeOverrideMember(actualMembers: List<IrDeclaration>, declaration: IrClass): IrOverridableDeclaration<*> {
return when (actualMembers.first()) {
is IrSimpleFunction -> createFakeOverrideFunction(actualMembers as List<IrSimpleFunction>, declaration)
is IrProperty -> createFakeOverrideProperty(actualMembers as List<IrProperty>, declaration)
else -> error("Only function or property can be overridden")
}
}
private fun createFakeOverrideProperty(actualProperties: List<IrProperty>, parent: IrClass): IrProperty {
val actualProperty = actualProperties.first() // TODO: Currently FIR2IR works in the similar way but it looks incorrect
return parent.factory.buildProperty {
updateFrom(actualProperty)
name = actualProperty.name
origin = IrDeclarationOrigin.FAKE_OVERRIDE
isFakeOverride = true
isExpect = false
}.apply {
this.parent = parent
annotations = actualProperty.annotations
backingField = null
getter = createFakeOverrideFunction(actualProperties.map { it.getter as IrSimpleFunction }, parent, symbol)
setter = runIf(actualProperty.setter != null) {
createFakeOverrideFunction(actualProperties.map { it.setter as IrSimpleFunction }, parent, symbol)
}
overriddenSymbols = actualProperties.map { it.symbol }
}
}
private fun createFakeOverrideFunction(
actualFunctions: List<IrSimpleFunction>,
parent: IrDeclarationParent,
correspondingPropertySymbol: IrPropertySymbol? = null
): IrSimpleFunction {
val actualFunction = actualFunctions.first() // TODO: Currently FIR2IR works in the similar way but it looks incorrect
return actualFunction.factory.buildFun {
updateFrom(actualFunction)
name = actualFunction.name
returnType = actualFunction.returnType
origin = IrDeclarationOrigin.FAKE_OVERRIDE
isFakeOverride = true
isExpect = false
}.also {
it.parent = parent
it.annotations = actualFunction.annotations.map { p -> p.deepCopyWithSymbols(it) }
it.typeParameters = actualFunction.typeParameters.map { p -> p.deepCopyWithSymbols(it) }
val typeRemapper = IrTypeParameterRemapper(actualFunction.typeParameters.zip(it.typeParameters).toMap())
fun IrValueParameter.deepCopyWithTypeParameters(): IrValueParameter = deepCopyWithSymbols(it) { symbolRemapper, _ ->
DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper)
}
it.dispatchReceiverParameter = actualFunction.dispatchReceiverParameter?.deepCopyWithTypeParameters()
it.extensionReceiverParameter = actualFunction.extensionReceiverParameter?.deepCopyWithTypeParameters()
it.valueParameters = actualFunction.valueParameters.map { p -> p.deepCopyWithTypeParameters() }
it.contextReceiverParametersCount = actualFunction.contextReceiverParametersCount
it.metadata = actualFunction.metadata
it.overriddenSymbols = actualFunctions.map { f -> f.symbol }
it.attributeOwnerId = it
it.correspondingPropertySymbol = correspondingPropertySymbol
}
}
@@ -1,147 +0,0 @@
/*
* 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.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.backend.common.CommonBackendErrors
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
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.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
import org.jetbrains.kotlin.name.FqName
internal class MissingFakeOverridesAdder(
private val expectActualMap: Map<IrSymbol, IrSymbol>,
private val typeAliasMap: Map<FqName, FqName>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) : IrElementVisitorVoid {
override fun visitClass(declaration: IrClass) {
if (!declaration.isExpect) {
processSupertypes(declaration)
}
visitElement(declaration)
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
private fun processSupertypes(declaration: IrClass) {
val members by lazy(LazyThreadSafetyMode.NONE) {
val notBuiltinMembers = declaration.declarations.filterNot { it.isBuiltinMember() }
val result = mutableMapOf<String, MutableList<IrDeclaration>>()
for (member in notBuiltinMembers) {
result.getOrPut(generateIrElementFullNameFromExpect(member, typeAliasMap)) { mutableListOf() }.add(member)
}
result
}
for (superType in declaration.superTypes) {
val expectClass = superType.classifierOrFail.owner as? IrClass ?: continue
val added = mutableSetOf<IrDeclaration>()
for (expectMember in expectClass.declarations) {
if (expectMember.isBuiltinMember()) continue
val actualMember = expectActualMap[expectMember.symbol]?.owner as? IrDeclaration ?: continue
added += actualMember
// Do not add FAKE_OVERRIDE if the subclass already has overridden member
if (declaration.declarations.filterIsInstance<IrOverridableDeclaration<*>>()
.any { expectMember.symbol in it.overriddenSymbols }
) {
continue
}
addFakeOverride(actualMember, members, declaration)
}
val actualClass = expectActualMap[expectClass.symbol]?.owner as? IrClass ?: continue
for (actualMember in actualClass.declarations) {
if (actualMember.isBuiltinMember() || actualMember in added) continue
if ((actualMember as? IrDeclarationWithVisibility)?.visibility == DescriptorVisibilities.PRIVATE) continue
addFakeOverride(actualMember, members, declaration)
}
}
}
private fun addFakeOverride(
actualMember: IrDeclaration,
members: MutableMap<String, MutableList<IrDeclaration>>,
declaration: IrClass
) {
val newMember = when (actualMember) {
is IrFunctionImpl -> createFakeOverrideFunction(actualMember, declaration)
is IrPropertyImpl -> createFakeOverrideProperty(actualMember, declaration)
else -> return
}
if (members.getMatches(newMember, expectActualMap, typeAliasMap).isEmpty()) {
declaration.declarations.add(newMember)
members.getOrPut(generateIrElementFullNameFromExpect(newMember, typeAliasMap)) { mutableListOf() }.add(newMember)
} else {
diagnosticsReporter.at(declaration).report(
CommonBackendErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED,
declaration.name.asString(),
(actualMember as IrDeclarationWithName).name.asString()
)
}
}
}
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) =
declaration.factory.buildProperty {
updateFrom(actualMember)
name = actualMember.name
origin = IrDeclarationOrigin.FAKE_OVERRIDE
}.apply {
parent = declaration
annotations = actualMember.annotations
backingField = actualMember.backingField
getter = (actualMember.getter as? IrFunctionImpl)?.let { getter ->
createFakeOverrideFunction(getter, declaration, symbol)
}
setter = (actualMember.setter as? IrFunctionImpl)?.let { setter ->
createFakeOverrideFunction(setter, declaration, symbol)
}
overriddenSymbols = listOf(actualMember.symbol)
}
private fun createFakeOverrideFunction(
actualFunction: IrFunctionImpl,
parent: IrDeclarationParent,
correspondingPropertySymbol: IrPropertySymbol? = null
) = actualFunction.factory.buildFun {
updateFrom(actualFunction)
name = actualFunction.name
returnType = actualFunction.returnType
origin = IrDeclarationOrigin.FAKE_OVERRIDE
isFakeOverride = true
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
}