Actualize `expect` declarations with in-module `actual` counterparts

It is crucial for the @OptionalAnnotation metadata serialization
correctness.

^KT-67340: Fixed
diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
index bfc3aa7..605ca14 100644
--- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
+++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt
@@ -147,7 +147,7 @@
         }
     }
 
-    val irActualizer = if (dependentIrFragments.isEmpty()) null else IrActualizer(
+    val irActualizer = IrActualizer(
         KtDiagnosticReporterWithImplicitIrBasedContext(
             fir2IrConfiguration.diagnosticReporter,
             fir2IrConfiguration.languageVersionSettings
@@ -164,11 +164,11 @@
         // So to avoid even more changes, when this mode is disabled, we don't run classifiers
         // actualization separately. This should go away, after useIrFakeOverrideBuilder becomes
         // always enabled
-        irActualizer?.actualizeClassifiers()
+        irActualizer.actualizeClassifiers()
         val temporaryResolver = SpecialFakeOverrideSymbolsResolver(emptyMap())
         platformComponentsStorage.fakeOverrideBuilder.buildForAll(dependentIrFragments + mainIrFragment, temporaryResolver)
     }
-    val expectActualMap = irActualizer?.actualizeCallablesAndMergeModules() ?: emptyMap()
+    val expectActualMap = irActualizer.actualizeCallablesAndMergeModules()
     val fakeOverrideResolver = runIf(!platformComponentsStorage.configuration.useFirBasedFakeOverrideGenerator) {
         val fakeOverrideResolver = SpecialFakeOverrideSymbolsResolver(expectActualMap)
         mainIrFragment.acceptVoid(SpecialFakeOverrideSymbolsResolverVisitor(fakeOverrideResolver))
@@ -177,7 +177,7 @@
         fakeOverrideResolver
     }
     Fir2IrConverter.evaluateConstants(mainIrFragment, platformComponentsStorage)
-    val actualizationResult = irActualizer?.runChecksAndFinalize(expectActualMap)
+    val actualizationResult = irActualizer.runChecksAndFinalize(expectActualMap)
 
     fakeOverrideResolver?.cacheFakeOverridesOfAllClasses(mainIrFragment)
 
diff --git a/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrActualizer.kt b/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrActualizer.kt
index 3ad61d0..d7a72a1 100644
--- a/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrActualizer.kt
+++ b/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrActualizer.kt
@@ -108,15 +108,15 @@
     fun runChecksAndFinalize(expectActualMap: Map<IrSymbol, IrSymbol>) : IrActualizedResult {
         //   Remove top-only expect declarations since they are not needed anymore and should not be presented in the final IrFragment
         //   Also, it doesn't remove unactualized expect declarations marked with @OptionalExpectation
-        val removedExpectDeclarations = removeExpectDeclarations(dependentFragments, expectActualMap)
+        val removedExpectDeclarations = removeExpectDeclarations(dependentFragments + mainFragment, expectActualMap)
 
         IrExpectActualCheckers(expectActualMap, classActualizationInfo, typeSystemContext, ktDiagnosticReporter).check()
         return IrActualizedResult(removedExpectDeclarations, expectActualMap)
     }
 
-    private fun removeExpectDeclarations(dependentFragments: List<IrModuleFragment>, expectActualMap: Map<IrSymbol, IrSymbol>): List<IrDeclaration> {
+    private fun removeExpectDeclarations(fragments: List<IrModuleFragment>, expectActualMap: Map<IrSymbol, IrSymbol>): List<IrDeclaration> {
         val removedExpectDeclarations = mutableListOf<IrDeclaration>()
-        for (fragment in dependentFragments) {
+        for (fragment in fragments) {
             for (file in fragment.files) {
                 file.declarations.removeIf {
                     if (shouldRemoveExpectDeclaration(it, expectActualMap)) {
diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt
index 1dcbb54..eb91265 100644
--- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt
+++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt
@@ -29,6 +29,7 @@
 import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
 import org.jetbrains.kotlin.fir.FirAnalyzerFacade
 import org.jetbrains.kotlin.fir.FirTestSessionFactoryHelper
+import org.jetbrains.kotlin.fir.backend.extractFirDeclarations
 import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
 import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
 import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions
@@ -121,12 +122,13 @@
         val fir2IrExtensions = JvmFir2IrExtensions(configuration, JvmIrDeserializerImpl(), JvmIrMangler)
         val diagnosticReporter = DiagnosticReporterFactory.createReporter()
         firAnalyzerFacade.runResolution()
-        val (moduleFragment, components, pluginContext) = firAnalyzerFacade.result.convertToIrAndActualizeForJvm(
-            fir2IrExtensions,
-            configuration,
-            diagnosticReporter,
-            irGeneratorExtensions = emptyList()
-        )
+        val (moduleFragment, components, pluginContext, actualizedExpectDeclarations) =
+            firAnalyzerFacade.result.convertToIrAndActualizeForJvm(
+                fir2IrExtensions,
+                configuration,
+                diagnosticReporter,
+                irGeneratorExtensions = emptyList()
+            )
 
         val dummyBindingContext = NoScopeRecordCliBindingTrace(project).bindingContext
 
@@ -148,8 +150,13 @@
         generationState.beforeCompile()
         generationState.oldBEInitTrace(files)
         codegenFactory.generateModuleInFrontendIRMode(
-            generationState, moduleFragment, components.symbolTable, components.irProviders,
-            fir2IrExtensions, FirJvmBackendExtension(components, actualizedExpectDeclarations = null), pluginContext,
+            generationState,
+            moduleFragment,
+            components.symbolTable,
+            components.irProviders,
+            fir2IrExtensions,
+            FirJvmBackendExtension(components, actualizedExpectDeclarations?.actualizedExpectDeclarations?.extractFirDeclarations()),
+            pluginContext,
         ) {}
 
         generationState.factory.done()
diff --git a/libraries/tools/kotlinp/jvm/testData/OptionalAnnotation.kt b/libraries/tools/kotlinp/jvm/testData/OptionalAnnotation.kt
index 367e5db..85fc91e 100644
--- a/libraries/tools/kotlinp/jvm/testData/OptionalAnnotation.kt
+++ b/libraries/tools/kotlinp/jvm/testData/OptionalAnnotation.kt
@@ -1,6 +1,3 @@
-// IGNORE K2
-// ^ KT-62931 K2: extra class files for @OptionalExpectation marked annotations
-
 // !LANGUAGE: +MultiPlatformProjects
 // !OPT_IN: kotlin.ExperimentalMultiplatform
 // NO_READ_WRITE_COMPARE