JVM IR: add module name for internal functions before "$default"
The change is a bit complicated because the name mapping logic is refactored so that we would compute the needed suffix first (either module name, or multifile part class name), and then shove it into the mangled name between the original function name and "$default", if the function in question is the default arguments adapter. The main motivation for this change was to fix KT-41809, but as a side effect, private functions with default arguments in multifile parts now also contain the file name, just like normal private functions. #KT-41809 Fixed
This commit is contained in:
+27
-14
@@ -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 != "<clinit>" && (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() != "<clinit>" &&
|
||||
(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)
|
||||
|
||||
+12
@@ -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 = "") {}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
@kotlin.Metadata
|
||||
public final class test/A {
|
||||
// source: 'internalNameMangling.kt'
|
||||
public method <init>(): void
|
||||
public method <init>(p0: int): void
|
||||
public synthetic method <init>(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
|
||||
}
|
||||
Vendored
+7
@@ -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 = "") {}
|
||||
Vendored
+11
@@ -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
|
||||
}
|
||||
Vendored
+13
@@ -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
|
||||
}
|
||||
+23
@@ -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)
|
||||
|
||||
+23
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user