[KLIB stdlib] Test visibility of intrinsics that can be used in KLIBs with inlined IR
^KT-69947 Fixed
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/CollectNotVisibleFromOriginalModuleIrVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/CollectNotVisibleFromOriginalModuleIrVisitor.kt
new file mode 100644
index 0000000..033036b
--- /dev/null
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/CollectNotVisibleFromOriginalModuleIrVisitor.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.ir.util
+
+import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
+import org.jetbrains.kotlin.ir.IrElement
+import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
+import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
+import org.jetbrains.kotlin.ir.expressions.IrCall
+import org.jetbrains.kotlin.ir.visitors.IrVisitorVoid
+import org.jetbrains.kotlin.name.FqName
+
+class CollectNotVisibleFromOriginalModuleIrVisitor(
+ private val notVisible: MutableList<IrSimpleFunction>,
+ private val originalModule: IrModuleFragment,
+) : IrVisitorVoid() {
+ override fun visitElement(element: IrElement) {
+ element.acceptChildren(this, null)
+ }
+
+ // TODO: Not just calls
+ override fun visitCall(expression: IrCall) {
+ val functionDeclaration = expression.symbol.owner
+ val module = functionDeclaration.fileOrNull?.module ?: return
+ if (originalModule == module && !isVisible(functionDeclaration)) {
+ notVisible.add(functionDeclaration)
+ }
+ super.visitCall(expression)
+ }
+
+ private fun isVisible(functionDeclaration: IrSimpleFunction): Boolean {
+ return functionDeclaration.fqNameWhenAvailable in FQ_NAMES_EXCLUDED_FROM_VISIBILITY_CHECKS ||
+ functionDeclaration.visibility == DescriptorVisibilities.PUBLIC ||
+ (functionDeclaration.visibility == DescriptorVisibilities.INTERNAL &&
+ functionDeclaration.annotations.hasAnnotation(publishedApiAnnotation))
+ }
+
+ private val publishedApiAnnotation = FqName("kotlin.PublishedApi")
+
+ // TODO: Discuss relation between KT-70295 and KT-69947
+ private val FQ_NAMES_EXCLUDED_FROM_VISIBILITY_CHECKS: Set<FqName> = listOf(
+ "kotlin.js.sharedBoxCreate",
+ "kotlin.js.sharedBoxWrite",
+ "kotlin.js.sharedBoxRead",
+ "kotlin.wasm.internal.ClosureBoxBoolean",
+ "kotlin.wasm.internal.ClosureBoxByte",
+ "kotlin.wasm.internal.ClosureBoxShort",
+ "kotlin.wasm.internal.ClosureBoxChar",
+ "kotlin.wasm.internal.ClosureBoxInt",
+ "kotlin.wasm.internal.ClosureBoxLong",
+ "kotlin.wasm.internal.ClosureBoxFloat",
+ "kotlin.wasm.internal.ClosureBoxDouble",
+ "kotlin.wasm.internal.ClosureBoxAny",
+ "kotlin.wasm.internal.wasmTypeId",
+ "kotlin.coroutines.CoroutineImpl",
+ "kotlin.native.internal.KClassImpl",
+ "kotlin.native.internal.KTypeImpl",
+ "kotlin.native.internal.KTypeProjectionList",
+ "kotlin.native.internal.KTypeParameterImpl",
+ ).mapTo(hashSetOf(), ::FqName)
+}
\ No newline at end of file
diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/StdlibVisibilityIrHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/StdlibVisibilityIrHandler.kt
new file mode 100644
index 0000000..9a13acc
--- /dev/null
+++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/StdlibVisibilityIrHandler.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.test.backend.handlers
+
+import org.jetbrains.kotlin.ir.IrElement
+import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
+import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
+import org.jetbrains.kotlin.ir.declarations.name
+import org.jetbrains.kotlin.ir.util.CollectNotVisibleFromOriginalModuleIrVisitor
+import org.jetbrains.kotlin.ir.util.file
+import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
+import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
+import org.jetbrains.kotlin.test.model.TestModule
+import org.jetbrains.kotlin.test.services.TestServices
+
+class StdlibVisibilityIrHandler(testServices: TestServices) : AbstractIrHandler(testServices) {
+ override fun processModule(module: TestModule, info: IrBackendInput) {
+ val stdlibModule = info.irPluginContext.irBuiltIns.anyClass.owner.file.module
+ val irFiles = info.irModuleFragment.files.sortedBy { it.name }
+ val notVisibleElements = irFiles.flatMap { collectNotVisibleElements(it, stdlibModule) }
+ assert(notVisibleElements.isEmpty()) { "Found not visible elements ${notVisibleElements.toSet().map { it.fqNameWhenAvailable }}" }
+ }
+
+ override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
+
+ private fun collectNotVisibleElements(element: IrElement, module: IrModuleFragment): List<IrSimpleFunction> =
+ buildList<IrSimpleFunction> {
+ element.accept(CollectNotVisibleFromOriginalModuleIrVisitor(this, module), null)
+ }
+}
\ No newline at end of file
diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsBlackBoxCodegenTestBase.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsBlackBoxCodegenTestBase.kt
index 512deb8..aa28c93 100644
--- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsBlackBoxCodegenTestBase.kt
+++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/AbstractJsBlackBoxCodegenTestBase.kt
@@ -154,7 +154,7 @@
is JsBackendFacades.WithSeparatedDeserialization -> {
configureInlinedIrHandlersStep { useHandlers(backendFacades.preSerializationHandler) }
facadeStep(backendFacades.deserializerFacade)
- deserializedIrHandlersStep { useHandlers(backendFacades.postDeserializationHandler) }
+ deserializedIrHandlersStep { useHandlers(backendFacades.postDeserializationHandler, ::StdlibVisibilityIrHandler) }
}
}
diff --git a/native/native.tests/klib-ir-inliner/tests/org/jetbrains/kotlin/konan/test/serialization/AbstractNativeIrDeserializationTest.kt b/native/native.tests/klib-ir-inliner/tests/org/jetbrains/kotlin/konan/test/serialization/AbstractNativeIrDeserializationTest.kt
index 12dde88..4e267fe 100644
--- a/native/native.tests/klib-ir-inliner/tests/org/jetbrains/kotlin/konan/test/serialization/AbstractNativeIrDeserializationTest.kt
+++ b/native/native.tests/klib-ir-inliner/tests/org/jetbrains/kotlin/konan/test/serialization/AbstractNativeIrDeserializationTest.kt
@@ -14,6 +14,7 @@
import org.jetbrains.kotlin.test.FirParser
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.BlackBoxCodegenSuppressor
+import org.jetbrains.kotlin.test.backend.handlers.StdlibVisibilityIrHandler
import org.jetbrains.kotlin.test.backend.handlers.IrMangledNameAndSignatureDumpHandler
import org.jetbrains.kotlin.test.backend.handlers.KlibAbiDumpHandler
import org.jetbrains.kotlin.test.backend.handlers.KlibBackendDiagnosticsHandler
@@ -173,5 +174,5 @@
klibArtifactsHandlersStep {
useHandlers(::KlibBackendDiagnosticsHandler)
}
- deserializedIrHandlersStep { useHandlers({ SerializedIrDumpHandler(it, isAfterDeserialization = true) }) }
+ deserializedIrHandlersStep { useHandlers({ SerializedIrDumpHandler(it, isAfterDeserialization = true)}, ::StdlibVisibilityIrHandler ) }
}