diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 2e62eeda0a7..23e64f09639 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -116,6 +116,12 @@ class Fir2IrConverter( } } + if (components.session.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) { + // See the comment to generateUnboundFakeOverrides function itself + @OptIn(LeakedDeclarationCaches::class) + declarationStorage.generateUnboundFakeOverrides() + } + evaluateConstants(irModuleFragment, components) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 7bf809555a9..eb6bc2fd8c2 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -1141,6 +1141,61 @@ class Fir2IrDeclarationStorage( } } + // ------------------------------------ binding unbound symbols ------------------------------------ + + /** + * This function iterates over all f/o symbols created in declaration storage and binds all unbound symbols + * + * Usually all symbols are bound after fir2ir conversion is over, but there is a case in MPP scenario when some fake-override + * for common classes appears only during conversion of platform session: + * + * // MODULE: common + * expect interface A + * + * interface B : A { + * // f/o fun foo() // (1) + * } + * + * // MODULE: platform()()(common) + * actual interface A { + * fun foo() // (2) + * } + * + * fun test(b: B) { + * b.foo() // (3) + * } + * + * Here during common module conversion there is no `foo` function in scope of class B, so (1) is not generated + * During conversion of function test we reference symbol for (1) at line (3), so this symbol is created. But + * there is no code which generate actual IR for this symbol, because IR for f/o is generated only during + * conversion of corresponing class (and `B` is already converted) + * + * So to fix this issue we need to call this method after conversion of platform module + */ + @LeakedDeclarationCaches + internal fun generateUnboundFakeOverrides() { + for ((identifier, symbol) in irForFirSessionDependantDeclarationMap) { + if (symbol.isBound) continue + val (originalSymbol, dispatchReceiverLookupTag, _) = identifier + val irParent = findIrParent(originalSymbol.fir, dispatchReceiverLookupTag) + when (originalSymbol) { + is FirPropertySymbol -> createAndCacheIrProperty( + originalSymbol.fir, + irParent, + fakeOverrideOwnerLookupTag = dispatchReceiverLookupTag + ) + + is FirNamedFunctionSymbol -> createAndCacheIrFunction( + originalSymbol.fir, + irParent, + fakeOverrideOwnerLookupTag = dispatchReceiverLookupTag + ) + + else -> error("Unexpected declaration: $originalSymbol") + } + } + } + // ------------------------------------ scripts ------------------------------------ fun getCachedIrScript(script: FirScript): IrScript? { diff --git a/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt b/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt index 2d2d17ef1b8..11228af140a 100644 --- a/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt +++ b/compiler/testData/codegen/box/multiplatform/hmpp/simple.kt @@ -6,9 +6,6 @@ // WITH_STDLIB // !LANGUAGE: +MultiPlatformProjects // IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-62535 -// IGNORE_BACKEND_K2: JVM_IR -// Ignore reason: (TODO) how should generate IR for common f/o after actualization? - // TARGET_BACKEND: JVM // MODULE: common // TARGET_PLATFORM: Common diff --git a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt index 23db46b193d..b5e7e36ae24 100644 --- a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt +++ b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes.kt @@ -3,9 +3,6 @@ // WITH_STDLIB // !LANGUAGE: +MultiPlatformProjects // IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-62535 -// IGNORE_BACKEND_K2: JVM_IR -// Ignore reason: (TODO) how should generate IR for common f/o after actualization? - // MODULE: common // TARGET_PLATFORM: Common // FILE: common.kt diff --git a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt index 191b0d9fe62..6507a795058 100644 --- a/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt +++ b/compiler/testData/codegen/box/multiplatform/k2/basic/expectInterfaceInSupertypes2.kt @@ -3,8 +3,6 @@ // WITH_STDLIB // IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-62535 // !LANGUAGE: +MultiPlatformProjects -// IGNORE_BACKEND_K2: JVM_IR -// Ignore reason: (TODO) how should generate IR for common f/o after actualization? // MODULE: common // TARGET_PLATFORM: Common