[klibs] header klibs should keep private interfaces

^KT-62213 Fixed
diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/serializationUtil.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/serializationUtil.kt
index ef0b7ff..f3333f8 100644
--- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/serializationUtil.kt
+++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/serializationUtil.kt
@@ -7,9 +7,11 @@
 
 import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
 import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.declarations.FirClass
 import org.jetbrains.kotlin.fir.declarations.FirDeclaration
 import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
 import org.jetbrains.kotlin.fir.declarations.utils.isExpect
+import org.jetbrains.kotlin.fir.declarations.utils.isInterface
 import org.jetbrains.kotlin.fir.declarations.utils.visibility
 import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
 import org.jetbrains.kotlin.fir.languageVersionSettings
@@ -54,4 +56,6 @@
 
 fun FirMemberDeclaration.isNotPrivateOrShouldBeSerialized(produceHeaderKlib: Boolean): Boolean {
     return !produceHeaderKlib || visibility.isPublicAPI
+            // Always keep private interfaces as they can be part of public type hierarchies.
+            || (this as? FirClass)?.isInterface == true
 }
diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt
index ceba63f..a54fbad 100644
--- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt
+++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrFileSerializer.kt
@@ -1271,6 +1271,8 @@
 
     private fun skipIfPrivate(declaration: IrDeclaration) =
         skipPrivateApi && (declaration as? IrDeclarationWithVisibility)?.visibility?.isPublicAPI != true
+                // Always keep private interfaces as they can be part of public type hierarchies.
+                && (declaration as? IrClass)?.isInterface != true
 
     open fun memberNeedsSerialization(member: IrDeclaration): Boolean {
         val parent = member.parent
diff --git a/native/native.tests/testData/klib/header-klibs/compilation/classes/lib/classes.kt b/native/native.tests/testData/klib/header-klibs/compilation/classes/lib/classes.kt
index a373a9d..0453621 100644
--- a/native/native.tests/testData/klib/header-klibs/compilation/classes/lib/classes.kt
+++ b/native/native.tests/testData/klib/header-klibs/compilation/classes/lib/classes.kt
@@ -5,7 +5,11 @@
     fun iMethod(): Int
 }
 
-open class A : I {
+private interface K {
+    fun kMethod() = 42
+}
+
+open class A : I, K {
     override val iProperty: Int = 0
     override fun iMethod(): Int = 10
 
diff --git a/native/native.tests/testData/klib/header-klibs/compilation/classes/main/main.kt b/native/native.tests/testData/klib/header-klibs/compilation/classes/main/main.kt
index 132858e..bc9b0d2 100644
--- a/native/native.tests/testData/klib/header-klibs/compilation/classes/main/main.kt
+++ b/native/native.tests/testData/klib/header-klibs/compilation/classes/main/main.kt
@@ -7,6 +7,10 @@
     i.iMethod()
 }
 
+fun useK(k: A) {
+    k.kMethod()
+}
+
 fun useA(a: A) {
     a.iProperty
     a.iMethod()
@@ -37,6 +41,7 @@
 
 fun runAppAndReturnOk(): String {
     useI(A())
+    useK(A())
     useA(A())
     useB(B())
     useC("test")