diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt index 21c5a495da6..8a9c86379c7 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/ExpectActualCollector.kt @@ -33,7 +33,7 @@ internal class ExpectActualCollector( } private fun MutableMap.appendExpectActualClassifiersMap(): Pair, Map> { - val actualClassifiers = mutableMapOf() + val actualClassifiers = mutableMapOf() // There is no list for builtins declarations; that's why they are being collected from typealiases val allActualDeclarations = mutableSetOf() val typeAliasMap = mutableMapOf() // It's used to link members from expect class that have typealias actual @@ -43,7 +43,7 @@ internal class ExpectActualCollector( ActualClassifiersCollector(actualClassifiers, allActualDeclarations, typeAliasMap).visitModuleFragment(fragment, false) } - val linkCollector = ClassifiersLinkCollector(this, actualClassifiers, diagnosticsReporter) + val linkCollector = ClassifiersLinkCollector(this, actualClassifiers, typeAliasMap, diagnosticsReporter) dependentFragments.forEach { linkCollector.visitModuleFragment(it) } return allActualDeclarations to typeAliasMap @@ -55,21 +55,21 @@ internal class ExpectActualCollector( ) { val actualMembers = mutableMapOf() - collectActualCallables(this, actualMembers, allActualDeclarations) + collectActualCallables(this, actualMembers, typeAliasMap, allActualDeclarations) val collector = CallablesLinkCollector(this, actualMembers, typeAliasMap, diagnosticsReporter) dependentFragments.forEach { collector.visitModuleFragment(it) } } } private class ActualClassifiersCollector( - private val actualClassifiers: MutableMap, + private val actualClassifiers: MutableMap, private val allActualClassifiers: MutableSet, private val typeAliasMap: MutableMap ) : IrElementVisitor { override fun visitTypeAlias(declaration: IrTypeAlias, data: Boolean) { if (declaration.isActual) { val expandedTypeSymbol = declaration.expandedType.classifierOrFail - actualClassifiers[declaration.kotlinFqName] = expandedTypeSymbol + actualClassifiers[generateIrElementFullName(declaration)] = expandedTypeSymbol if (expandedTypeSymbol is IrClassSymbol) { allActualClassifiers.add(expandedTypeSymbol.owner) typeAliasMap[declaration.kotlinFqName] = expandedTypeSymbol.owner.kotlinFqName @@ -80,19 +80,14 @@ private class ActualClassifiersCollector( override fun visitClass(declaration: IrClass, data: Boolean) { if (!data && !declaration.isExpect) { - actualClassifiers[declaration.kotlinFqName] = declaration.symbol + actualClassifiers[generateIrElementFullName(declaration)] = declaration.symbol } visitDeclaration(declaration, data) } override fun visitEnumEntry(declaration: IrEnumEntry, data: Boolean) { if (!data && !declaration.isExpect) { - actualClassifiers[FqName.fromSegments( - listOf( - declaration.parent.kotlinFqName.asString(), - declaration.name.asString() - ) - )] = declaration.symbol + actualClassifiers[generateIrElementFullName(declaration)] = declaration.symbol } visitDeclaration(declaration, data) } @@ -111,11 +106,12 @@ private class ActualClassifiersCollector( private class ClassifiersLinkCollector( private val expectActualMap: MutableMap, - private val actualClassifiers: Map, + private val actualClassifiers: Map, + private val typeAliasMap: Map, private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext ) : IrElementVisitorVoid { - private fun addLinkOrReportMissing(expectElement: IrDeclaration, actualTypeId: FqName) { - val actualClassifier = actualClassifiers[actualTypeId] + private fun addLinkOrReportMissing(expectElement: IrDeclaration) { + val actualClassifier = actualClassifiers[generateIrElementFullName(expectElement, expectActualMap, typeAliasMap)] if (actualClassifier != null) { expectActualMap[expectElement.symbol] = actualClassifier } else if (!expectElement.containsOptionalExpectation()) { @@ -125,16 +121,14 @@ private class ClassifiersLinkCollector( override fun visitClass(declaration: IrClass) { if (declaration.isExpect) { - addLinkOrReportMissing(declaration, declaration.kotlinFqName) + addLinkOrReportMissing(declaration) } visitElement(declaration) } override fun visitEnumEntry(declaration: IrEnumEntry) { if (declaration.isProperExpect) { - addLinkOrReportMissing( - declaration, FqName.fromSegments(listOf(declaration.parent.kotlinFqName.asString(), declaration.name.asString())) - ) + addLinkOrReportMissing(declaration) } visitElement(declaration) } @@ -147,13 +141,14 @@ private class ClassifiersLinkCollector( private fun collectActualCallables( expectActualMap: MutableMap, actualMembers: MutableMap, + typeAliasMap: Map, allActualDeclarations: Set, ) { fun collectActualsCallables(declaration: IrDeclaration) { when (declaration) { is IrFunction, is IrProperty -> { - actualMembers[generateIrElementFullName(declaration, expectActualMap)] = declaration as IrDeclarationBase + actualMembers[generateIrElementFullName(declaration, expectActualMap, typeAliasMap)] = declaration as IrDeclarationBase } is IrClass -> { for (member in declaration.declarations) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt index 9bd603cdadd..f47979040cd 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrActualizerUtils.kt @@ -22,23 +22,40 @@ import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil fun generateIrElementFullName( declaration: IrElement, - expectActualTypesMap: Map, + expectActualTypesMap: Map? = null, typeAliasMap: Map? = null ): String { - return StringBuilder().apply { appendElementFullName(declaration, expectActualTypesMap, this, typeAliasMap) }.toString() + return StringBuilder().apply { appendElementFullName(declaration, this, expectActualTypesMap, typeAliasMap) }.toString() } private fun appendElementFullName( declaration: IrElement, - expectActualTypesMap: Map, result: StringBuilder, - typeAliasMap: Map? = null + expectActualTypesMap: Map? = null, + expectActualTypeAliasMap: Map? = null ) { if (declaration !is IrDeclarationBase) return - val parentName = declaration.parent.kotlinFqName - if (parentName.asString().isNotEmpty()) { - result.append(typeAliasMap?.get(parentName) ?: parentName.asString()) + val parents = mutableListOf() + var parent: IrDeclarationParent? = declaration.parent + while (parent != null) { + if (parent is IrDeclarationWithName) { + val parentParent = parent.parent + if (parentParent is IrClass) { + parents.add(parent.name.asString()) + parent = parentParent + continue + } + } + val parentString = parent.kotlinFqName.let { (expectActualTypeAliasMap?.get(it) ?: it).asString() } + if (parentString.isNotEmpty()) { + parents.add(parentString) + } + parent = null + } + + if (parents.isNotEmpty()) { + result.append(parents.asReversed().joinToString(separator = ".")) result.append('.') } @@ -49,8 +66,8 @@ private fun appendElementFullName( if (declaration is IrFunction) { fun appendType(type: IrType) { val typeClassifier = type.classifierOrFail - val actualizedTypeSymbol = expectActualTypesMap[typeClassifier] ?: typeClassifier - appendElementFullName(actualizedTypeSymbol.owner, expectActualTypesMap, result) + val actualizedTypeSymbol = expectActualTypesMap?.get(typeClassifier) ?: typeClassifier + appendElementFullName(actualizedTypeSymbol.owner, result, expectActualTypesMap) } val extensionReceiverType = declaration.extensionReceiverParameter?.type diff --git a/compiler/testData/diagnostics/tests/multiplatform/sealedTypeAlias.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/sealedTypeAlias.fir.kt deleted file mode 100644 index f91761cd233..00000000000 --- a/compiler/testData/diagnostics/tests/multiplatform/sealedTypeAlias.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// MODULE: m1-common -// FILE: common.kt - -expect sealed class Presence { - object Online: Presence - object Offline: Presence -} - -// MODULE: m2-jvm()()(m1-common) -// FILE: jvm.kt - -actual typealias Presence = P -sealed class P { - object Online : P() - object Offline : P() -} diff --git a/compiler/testData/diagnostics/tests/multiplatform/sealedTypeAlias.kt b/compiler/testData/diagnostics/tests/multiplatform/sealedTypeAlias.kt index 0325dfbfc1b..e62094269af 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/sealedTypeAlias.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/sealedTypeAlias.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // MODULE: m1-common // FILE: common.kt