[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")