WIP! Wed Jul  3 16:25:18 CEST 2024 debug
diff --git a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/AbstractSymbolLightClassesAnnotationEqualityTest.kt b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/AbstractSymbolLightClassesAnnotationEqualityTest.kt
index edba05e..9efc57d 100644
--- a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/AbstractSymbolLightClassesAnnotationEqualityTest.kt
+++ b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/base/AbstractSymbolLightClassesAnnotationEqualityTest.kt
@@ -31,7 +31,7 @@
 ) : AbstractSymbolLightClassesTestBase(configurator) {
     override fun doLightClassTest(ktFiles: List<KtFile>, module: KtTestModule, testServices: TestServices) {
         val directives = module.testModule.directives
-        val expectedAnnotations = directives[Directives.EXPECTED]
+        val expectedAnnotations: List<AnnotationData> = directives[Directives.EXPECTED]
         val unexpectedAnnotations = directives[Directives.UNEXPECTED]
         val qualifiersToCheck = expectedAnnotations + unexpectedAnnotations
         testServices.assertions.assertTrue(qualifiersToCheck.isNotEmpty()) { error("Nothing to check") }
diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt
index 2693673..ff09563 100644
--- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt
+++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt
@@ -70,7 +70,7 @@
             val providers = createProviders(this, builtinsModuleData, kotlinScopeProvider, syntheticFunctionInterfaceProvider)
 
             val symbolProvider = FirCachingCompositeSymbolProvider(this, providers)
-            register(FirSymbolProvider::class, symbolProvider)
+            register(FirSymbolProvider::class, symbolProvider) // symbolProvider
             register(FirProvider::class, FirLibrarySessionProvider(symbolProvider))
         }
     }
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 282ce8c..25241cf 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
@@ -463,7 +463,7 @@
         val symbol = IrConstructorSymbolImpl() // unbound instance
         if (potentiallyExternal) {
             val irParent = findIrParent(constructor, fakeOverrideOwnerLookupTag = null)
-            if (irParent.isExternalParent()) {
+            if (irParent.isExternalParent()) { // suka zdes
                 callablesGenerator.createIrConstructor(
                     constructor,
                     irParent as IrClass,
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt
index 3d72f04..89b99bd 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt
@@ -710,7 +710,7 @@
 ): ConeDiagnostic {
     val symbol = candidate.symbol
     return when (applicability) {
-        CandidateApplicability.HIDDEN -> ConeHiddenCandidateError(candidate)
+        CandidateApplicability.HIDDEN_EXPECT, CandidateApplicability.HIDDEN -> ConeHiddenCandidateError(candidate)
         CandidateApplicability.K2_VISIBILITY_ERROR -> {
             val session = candidate.callInfo.session
 
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt
index 7c6ea37..a0e6f25 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt
@@ -9,10 +9,10 @@
 import org.jetbrains.kotlin.fir.*
 import org.jetbrains.kotlin.fir.declarations.*
 import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
+import org.jetbrains.kotlin.fir.declarations.utils.isExpect
 import org.jetbrains.kotlin.fir.declarations.utils.isInner
 import org.jetbrains.kotlin.fir.declarations.utils.isLocal
 import org.jetbrains.kotlin.fir.diagnostics.*
-import org.jetbrains.kotlin.fir.expressions.FirExpression
 import org.jetbrains.kotlin.fir.resolve.*
 import org.jetbrains.kotlin.fir.resolve.calls.AbstractCallInfo
 import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate
@@ -94,6 +94,7 @@
         val containingDeclarations = scopeClassDeclaration.containingDeclarations
 
         fun processCandidate(symbol: FirBasedSymbol<*>, substitutor: ConeSubstitutor?) {
+            println("--- ${(symbol as? FirClassLikeSymbol)?.classId}")
             var symbolApplicability = CandidateApplicability.RESOLVED
             var diagnostic: ConeDiagnostic? = null
 
@@ -102,6 +103,11 @@
                 diagnostic = ConeVisibilityError(symbol)
             }
 
+            if (!session.moduleData.isCommon && symbol is FirRegularClassSymbol && symbol.name.asString() == "Foo" && symbol.isExpect) {
+                symbolApplicability = minOf(CandidateApplicability.HIDDEN_EXPECT, symbolApplicability)
+                diagnostic = null
+            }
+
             if (resolveDeprecations) {
                 if (symbol.isDeprecationLevelHidden(session)) {
                     symbolApplicability = minOf(CandidateApplicability.HIDDEN, symbolApplicability)
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatcherTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatcherTransformer.kt
index a5425b7..0308fd2 100644
--- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatcherTransformer.kt
+++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatcherTransformer.kt
@@ -10,10 +10,14 @@
 import org.jetbrains.kotlin.fir.declarations.*
 import org.jetbrains.kotlin.fir.declarations.utils.isActual
 import org.jetbrains.kotlin.fir.declarations.utils.isExpect
+import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName
 import org.jetbrains.kotlin.fir.expectActualMatchingContextFactory
 import org.jetbrains.kotlin.fir.expressions.FirStatement
 import org.jetbrains.kotlin.fir.languageVersionSettings
+import org.jetbrains.kotlin.fir.moduleData
 import org.jetbrains.kotlin.fir.resolve.ScopeSession
+import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider
+import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
 import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractTreeTransformer
 import org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor
 import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -97,6 +101,12 @@
         if (memberDeclaration.isExpect) return
         val actualSymbol = memberDeclaration.symbol
 
+        val foo = session.moduleData.platform.joinToString()
+        val bar = memberDeclaration.nameOrSpecialName
+        val provider = session.symbolProvider
+        val deps = session.dependenciesSymbolProvider
+        println()
+
         // Regardless of whether any `expect` symbols are found for `memberDeclaration`, it must be assigned an `expectForActual` map.
         // Otherwise, `FirExpectActualDeclarationChecker` will assume that the symbol needs no checking and not report an
         // `EXPECT_WITHOUT_ACTUAL` error.
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt
index 18016c3..909f0f0 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt
@@ -5,7 +5,6 @@
 
 package org.jetbrains.kotlin.resolve.calls.tower
 
-import org.jetbrains.kotlin.builtins.StandardNames
 import org.jetbrains.kotlin.config.LanguageFeature
 import org.jetbrains.kotlin.config.LanguageVersionSettings
 import org.jetbrains.kotlin.contracts.EffectSystem
@@ -365,7 +364,8 @@
         val applicability = getResultApplicability(diagnostics)
         return applicability == CandidateApplicability.INAPPLICABLE ||
                 applicability == CandidateApplicability.INAPPLICABLE_WRONG_RECEIVER ||
-                applicability == CandidateApplicability.HIDDEN
+                applicability == CandidateApplicability.HIDDEN ||
+                applicability == CandidateApplicability.HIDDEN_EXPECT
     }
 
     // true if we found something
diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt
index d71be9e..48654aa 100644
--- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt
+++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt
@@ -5,7 +5,7 @@
 
 package org.jetbrains.kotlin.resolve.calls.tower
 
-enum class CandidateApplicability {
+enum class CandidateApplicability { // interesting!
     /**
      * Special applicability for migration warning up to 1.5.
      * Used when resolved to function with SAM conversion and array without spread as vararg.
@@ -13,6 +13,11 @@
     K1_RESOLVED_TO_SAM_WITH_VARARG,
 
     /**
+     * todo
+     */
+    HIDDEN_EXPECT,
+
+    /**
      * Candidate is removed from resolve due to SinceKotlin with later version or Deprecation with hidden level.
      * Note that SinceKotlin does not filter out classifier symbols and property accessors. Those
      * should lead to API_NOT_AVAILABLE.
diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt
index 518f475..b49a917 100644
--- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt
+++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt
@@ -481,7 +481,9 @@
         override fun getFinalCandidates(): Collection<C> {
             val moreSuitableGroup = candidateGroups.maxByOrNull { it.groupApplicability } ?: return emptyList()
             val groupApplicability = moreSuitableGroup.groupApplicability
-            if (groupApplicability == CandidateApplicability.HIDDEN) return emptyList()
+            if (groupApplicability == CandidateApplicability.HIDDEN || groupApplicability == CandidateApplicability.HIDDEN_EXPECT) {
+                return emptyList()
+            }
 
             return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability }
         }
diff --git a/compiler/testData/codegen/box/multiplatform/k2/implicitActualization/implicitActualizationToBinaryJava.kt b/compiler/testData/codegen/box/multiplatform/k2/implicitActualization/implicitActualizationToBinaryJava.kt
index f132933..76dcb2b 100644
--- a/compiler/testData/codegen/box/multiplatform/k2/implicitActualization/implicitActualizationToBinaryJava.kt
+++ b/compiler/testData/codegen/box/multiplatform/k2/implicitActualization/implicitActualizationToBinaryJava.kt
@@ -17,12 +17,13 @@
     fun foo(): Int // 5
 }
 
-fun common(): Int = Foo().foo() //* Foo().commonFakeOverride() * Foo().commonOverride()
+fun common(): Int = 5 // Foo().foo() //* Foo().commonFakeOverride() * Foo().commonOverride()
 
 // MODULE: lib()()()
 // FILE: Foo.java
 public class Foo {
     public int foo() { return 5; }
+    public void javaLib() {}
     // @Override public int commonOverride() { return 7; }
 }
 
@@ -34,8 +35,11 @@
 
 // MODULE: platform(lib)()(common)
 // FILE: jvm.kt
+fun unused(): Foo = null!!
+
 fun box(): String {
     val expect = 2 * 5 * 7
     val actual = common()
+    Foo().javaLib()
     return if (expect == actual) "OK" else "FAIL $expect $actual"
 }