diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt index 8f598f7f399..1fd565e47e1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.codegen.replaceValueParametersIn import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter import org.jetbrains.kotlin.codegen.state.JVM_SUPPRESS_WILDCARDS_ANNOTATION_FQ_NAME -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.extractTypeMappingModeFromAnnotation import org.jetbrains.kotlin.codegen.state.isMethodWithDeclarationSiteWildcardsFqName import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -45,6 +44,7 @@ import org.jetbrains.kotlin.load.kotlin.signatures import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil +import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature @@ -108,25 +108,38 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { private fun mangleMemberNameIfRequired(name: String, function: IrSimpleFunction): String { val newName = JvmCodegenUtil.sanitizeNameIfNeeded(name, context.state.languageVersionSettings) - if (function.isTopLevel) { - if (DescriptorVisibilities.isPrivate(function.suspendFunctionOriginal().visibility) && - newName != "" && (function.parent as? IrClass)?.attributeOwnerId in context.multifileFacadeForPart - ) { - return "$newName$${function.parentAsClass.name.asString()}" - } - return newName + val suffix = when { + function.isTopLevel -> + if (function.isInvisibleInMultifilePart()) function.parentAsClass.name.asString() else null + function.shouldMangleAsInternal() -> + NameUtils.sanitizeAsJavaIdentifier(getModuleName(function)) + else -> null + } ?: return newName + + if (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) { + assert(newName.endsWith(JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX)) { "Default adapter should end with \$default: ${function.render()}" } + return newName.substringBeforeLast(JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX) + "$" + suffix + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX } - return if (function.shouldMangleAsInternal()) - KotlinTypeMapper.InternalNameMapper.mangleInternalName(newName, getModuleName(function)) - else - newName + return "$newName$$suffix" } + private fun IrSimpleFunction.isInvisibleInMultifilePart(): Boolean = + name.asString() != "" && + (parent as? IrClass)?.attributeOwnerId in context.multifileFacadeForPart && + (DescriptorVisibilities.isPrivate(suspendFunctionOriginal().visibility) || + originalForDefaultAdapter?.isInvisibleInMultifilePart() == true) + private fun IrSimpleFunction.shouldMangleAsInternal(): Boolean = - origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR && + (origin != JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_CONSTRUCTOR && visibility == DescriptorVisibilities.INTERNAL && - !isPublishedApi() + !isPublishedApi()) + || originalForDefaultAdapter?.shouldMangleAsInternal() == true + + private val IrSimpleFunction.originalForDefaultAdapter: IrSimpleFunction? + get() = if (origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) { + ((body?.statements?.lastOrNull() as? IrReturn)?.value as? IrCall)?.symbol?.owner + } else null private fun getModuleName(function: IrSimpleFunction): String = (if (function is IrLazyFunction) diff --git a/compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.kt b/compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.kt new file mode 100644 index 00000000000..8713c0b1785 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.kt @@ -0,0 +1,12 @@ +// WITH_RUNTIME + +package test + +class A internal constructor(a: Int = 0) { + internal fun internalFunction(b: String = "") {} + + @JvmName("internalJvmNameFunction") + internal fun f(c: String = "") {} + + public fun publicFunction(d: String = "") {} +} diff --git a/compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.txt b/compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.txt new file mode 100644 index 00000000000..88b8e9a6386 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.txt @@ -0,0 +1,13 @@ +@kotlin.Metadata +public final class test/A { + // source: 'internalNameMangling.kt' + public method (): void + public method (p0: int): void + public synthetic method (p0: int, p1: int, p2: kotlin.jvm.internal.DefaultConstructorMarker): void + public synthetic static method internalFunction$test_module$default(p0: test.A, p1: java.lang.String, p2: int, p3: java.lang.Object): void + public final method internalFunction$test_module(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public synthetic static method internalJvmNameFunction$default(p0: test.A, p1: java.lang.String, p2: int, p3: java.lang.Object): void + public final @kotlin.jvm.JvmName method internalJvmNameFunction(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public synthetic static method publicFunction$default(p0: test.A, p1: java.lang.String, p2: int, p3: java.lang.Object): void + public final method publicFunction(@org.jetbrains.annotations.NotNull p0: java.lang.String): void +} diff --git a/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.kt b/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.kt new file mode 100644 index 00000000000..09df7d16058 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.kt @@ -0,0 +1,7 @@ +// WITH_RUNTIME +// The remaining differences of JVM and JVM_IR here are reported at KT-36970, KT-41841. + +@file:JvmMultifileClass +@file:JvmName("A") + +private fun foo(x: String = "") {} diff --git a/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.txt b/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.txt new file mode 100644 index 00000000000..ed08c63abd7 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.txt @@ -0,0 +1,11 @@ +@kotlin.Metadata +public final class A { + // source: 'privateFunctionInMultifilePart.kt' +} + +@kotlin.Metadata +synthetic final class A__PrivateFunctionInMultifilePartKt { + // source: 'privateFunctionInMultifilePart.kt' + synthetic static method foo$A__PrivateFunctionInMultifilePartKt$default(p0: java.lang.String, p1: int, p2: java.lang.Object): void + private final static method foo$A__PrivateFunctionInMultifilePartKt(p0: java.lang.String): void +} diff --git a/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart_ir.txt b/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart_ir.txt new file mode 100644 index 00000000000..60fbfc17c29 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart_ir.txt @@ -0,0 +1,13 @@ +@kotlin.Metadata +public final class A { + // source: 'privateFunctionInMultifilePart.kt' + final static method foo$A__PrivateFunctionInMultifilePartKt$default(@org.jetbrains.annotations.Nullable p0: java.lang.String, p1: int, p2: java.lang.Object): void +} + +@kotlin.Metadata +@kotlin.jvm.JvmName +synthetic final class A__PrivateFunctionInMultifilePartKt { + // source: 'privateFunctionInMultifilePart.kt' + synthetic static method foo$A__PrivateFunctionInMultifilePartKt$default(p0: java.lang.String, p1: int, p2: java.lang.Object): void + private final static method foo$A__PrivateFunctionInMultifilePartKt(p0: java.lang.String): void +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 488ff8bf96b..193d2dcc923 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -375,6 +375,29 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeListing/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractBytecodeListingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("internalNameMangling.kt") + public void testInternalNameMangling() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.kt"); + } + + @TestMetadata("privateFunctionInMultifilePart.kt") + public void testPrivateFunctionInMultifilePart() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeListing/deprecated") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index 43f6da344cf..093a1170e5c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -345,6 +345,29 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes } } + @TestMetadata("compiler/testData/codegen/bytecodeListing/defaultArguments") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DefaultArguments extends AbstractIrBytecodeListingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInDefaultArguments() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/defaultArguments"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @TestMetadata("internalNameMangling.kt") + public void testInternalNameMangling() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/defaultArguments/internalNameMangling.kt"); + } + + @TestMetadata("privateFunctionInMultifilePart.kt") + public void testPrivateFunctionInMultifilePart() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/defaultArguments/privateFunctionInMultifilePart.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeListing/deprecated") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)