Files
kotlin-fork/compiler/testData/klibABI/changeFunctionVisibility/main/m.kt
T
Dmitriy Dolovov 7382b31fdc [PL] Native: Remove harmful private visibility guard in deserialization of LazyIr
Kotlin/Native codegen needs to deserialize all fields throughout the class hierarchy to build the proper binary class layout. That becomes impossible with the guard condition that prevents loading private top-level classes from another module in LazyIR (see https://github.com/JetBrains/kotlin/blob/2a4d8800374578c1aa9ec9c996b393a98f5a6e3b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanIrlinker.kt#L701). The guard suits well for the partial linkage needs, but it causes the codegen to fail with `Unbound public symbol IrClassPublicSymbolImpl: [ File '/file/in/the/library.kt' <- private.top.level/ClassDeclaration|null[0] ]` error.

To prevent this the guard is removed. This does not influence the partial linkage in general except for the different error message being generated: `Function 'foo' can not be called: Private function declared in module <A> can not be accessed in module <B>` instead of `Function 'foo' can not be called: No function found for symbol '<symbol>'`.

#KT-54469
2023-03-27 15:50:13 +02:00

72 lines
5.6 KiB
Kotlin
Vendored

import abitestutils.abiTest
import abitestutils.TestBuilder
import abitestutils.TestMode.NATIVE_CACHE_STATIC_EVERYWHERE
fun box() = abiTest {
val c = Container()
val ci = ContainerImpl()
success("publicToInternalTopLevelFunction.v2") { publicToInternalTopLevelFunction() } // Signature remains the same.
success("publicToInternalPATopLevelFunction.v2") { publicToInternalPATopLevelFunction() } // Signature remains the same.
unlinkedTopLevelPrivateSymbol("/publicToPrivateTopLevelFunction") { publicToPrivateTopLevelFunction() } // Signature changed.
success("Container.publicToProtectedFunction.v2") { c.publicToProtectedFunction() } // Signature remains the same.
success("Container.publicToProtectedFunction.v2") { ci.publicToProtectedFunction() } // Signature remains the same.
success("Container.publicToInternalFunction.v2") { c.publicToInternalFunction() } // Signature remains the same.
unlinkedSymbol("/ContainerImpl.publicToInternalFunction") { ci.publicToInternalFunction() } // FOs are not generated for internal members from other module.
success("Container.publicToInternalPAFunction.v2") { c.publicToInternalPAFunction() } // Signature remains the same.
unlinkedSymbol("/ContainerImpl.publicToInternalPAFunction") { ci.publicToInternalPAFunction() } // FOs are not generated for internal members from other module.
inaccessible("publicToPrivateFunction") { c.publicToPrivateFunction() } // Inaccessible from other module though signature remains the same.
unlinkedSymbol("/ContainerImpl.publicToPrivateFunction") { ci.publicToPrivateFunction() } // FOs are not generated for private members.
success("Container.publicToProtectedFunction.v2") { ci.publicToProtectedFunctionAccess() } // Signature remains the same.
unlinkedSymbol("/ContainerImpl.publicToInternalFunction") { ci.publicToInternalFunctionAccess() } // FOs are not generated for internal members from other module.
unlinkedSymbol("/ContainerImpl.publicToInternalPAFunction") { ci.publicToInternalPAFunctionAccess() } // FOs are not generated for internal members from other module.
unlinkedSymbol("/ContainerImpl.publicToPrivateFunction") { ci.publicToPrivateFunctionAccess() } // FOs are not generated for private members.
success("Container.protectedToPublicFunction.v2") { ci.protectedToPublicFunctionAccess() } // Signature remains the same.
unlinkedSymbol("/ContainerImpl.protectedToInternalFunction") { ci.protectedToInternalFunctionAccess() } // FOs are not generated for internal members from other module.
unlinkedSymbol("/ContainerImpl.protectedToInternalPAFunction") { ci.protectedToInternalPAFunctionAccess() } // FOs are not generated for internal members from other module.
unlinkedSymbol("/ContainerImpl.protectedToPrivateFunction") { ci.protectedToPrivateFunctionAccess() } // FOs are not generated for private members.
success("ContainerImpl.publicToProtectedOverriddenFunction") { ci.publicToProtectedOverriddenFunction() }
success("ContainerImpl.publicToInternalOverriddenFunction") { ci.publicToInternalOverriddenFunction() }
success("ContainerImpl.publicToInternalPAOverriddenFunction") { ci.publicToInternalPAOverriddenFunction() }
success("ContainerImpl.publicToPrivateOverriddenFunction") { ci.publicToPrivateOverriddenFunction() }
success("ContainerImpl.protectedToPublicOverriddenFunction") { ci.protectedToPublicOverriddenFunctionAccess() }
success("ContainerImpl.protectedToInternalOverriddenFunction") { ci.protectedToInternalOverriddenFunctionAccess() }
success("ContainerImpl.protectedToInternalPAOverriddenFunction") { ci.protectedToInternalPAOverriddenFunctionAccess() }
success("ContainerImpl.protectedToPrivateOverriddenFunction") { ci.protectedToPrivateOverriddenFunctionAccess() }
success("ContainerImpl.newPublicFunction") { ci.newPublicFunction() }
success("ContainerImpl.newOpenPublicFunction") { ci.newOpenPublicFunction() }
success("ContainerImpl.newProtectedFunction") { ci.newProtectedFunctionAccess() }
success("ContainerImpl.newOpenProtectedFunction") { ci.newOpenProtectedFunctionAccess() }
success("ContainerImpl.newInternalFunction") { ci.newInternalFunctionAccess() }
success("ContainerImpl.newOpenInternalFunction") { ci.newOpenInternalFunctionAccess() }
success("ContainerImpl.newInternalPAFunction") { ci.newInternalPAFunctionAccess() }
success("ContainerImpl.newOpenInternalPAFunction") { ci.newOpenInternalPAFunctionAccess() }
success("ContainerImpl.newPrivateFunction") { ci.newPrivateFunctionAccess() }
}
// Shortcuts:
private inline fun TestBuilder.success(expectedOutcome: String, noinline block: () -> String) =
expectSuccess(expectedOutcome, block)
private inline fun TestBuilder.unlinkedSymbol(signature: String, noinline block: () -> Unit) {
val functionName = signature.removePrefix("/").substringAfterLast(".")
expectFailure(linkage("Function '$functionName' can not be called: No function found for symbol '$signature'"), block)
}
private inline fun TestBuilder.unlinkedTopLevelPrivateSymbol(signature: String, noinline block: () -> Unit) {
if (testMode == NATIVE_CACHE_STATIC_EVERYWHERE) {
val functionName = signature.removePrefix("/").substringAfterLast(".")
expectFailure(linkage("Function '$functionName' can not be called: Private function declared in module <lib1> can not be accessed in module <main>"), block)
} else
unlinkedSymbol(signature, block)
}
private inline fun TestBuilder.inaccessible(functionName: String, noinline block: () -> Unit) = expectFailure(
linkage("Function '$functionName' can not be called: Private function declared in module <lib1> can not be accessed in module <main>"),
block
)