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 ef0b7ff44ad..f3333f82995 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 @@ package org.jetbrains.kotlin.fir.serialization 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.isNotExpectOrShouldBeSerialized(actualizedExpectDeclara 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 ceba63f7f79..a54fbad1286 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 @@ open class IrFileSerializer( 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 a373a9d8574..0453621faa4 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 @@ interface I { 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 132858ea3e6..bc9b0d24400 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 @@ fun useI(i: I) { i.iMethod() } +fun useK(k: A) { + k.kMethod() +} + fun useA(a: A) { a.iProperty a.iMethod() @@ -37,6 +41,7 @@ fun useC(b: String) { fun runAppAndReturnOk(): String { useI(A()) + useK(A()) useA(A()) useB(B()) useC("test")