From 9c4f8f7e54209a8c4d890b7ae3be5cb39e5ea19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Wed, 20 Jan 2021 12:57:18 +0100 Subject: [PATCH] JVM IR: Fix signature mapping for inline classes using new mangling When resolving inline class methods in binary dependencies we look for methods matching both the new and the old mangling scheme. On the IR backend the method signature has to be computed for the inline class replacement, since the logic for signature mangling is not contained in the method signature mapping, unlike in the old backend. --- ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ .../backend/jvm/codegen/irCodegenUtils.kt | 5 ++-- .../MemoizedInlineClassReplacements.kt | 30 ++++++++++++++----- .../inlineClassInlineFunctionCall.kt | 11 +++++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ ...mpileKotlinAgainstKotlinTestGenerated.java | 5 ++++ .../ir/JvmIrAgainstOldBoxTestGenerated.java | 5 ++++ .../ir/JvmOldAgainstIrBoxTestGenerated.java | 5 ++++ 8 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java index 58b13168908..0de6b68c39a 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/FirCompileKotlinAgainstKotlinTestGenerated.java @@ -165,6 +165,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); } + @TestMetadata("inlineClassInlineFunctionCall.kt") + public void testInlineClassInlineFunctionCall() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt"); + } + @TestMetadata("inlineClassInlineProperty.kt") public void testInlineClassInlineProperty() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index b15d89c81ff..1dcae594b3d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -382,14 +382,13 @@ val IrMemberAccessExpression<*>.psiElement: PsiElement? fun IrSimpleType.isRawType(): Boolean = hasAnnotation(JvmGeneratorExtensions.RAW_TYPE_ANNOTATION_FQ_NAME) -internal fun classFileContainsMethod(function: IrFunction, context: JvmBackendContext, name: String): Boolean? { - val classId = function.parentClassId ?: return null +internal fun classFileContainsMethod(classId: ClassId, function: IrFunction, context: JvmBackendContext): Boolean? { val originalDescriptor = context.methodSignatureMapper.mapSignatureWithGeneric(function).asmMethod.descriptor val descriptor = if (function.isSuspend) listOf(*Type.getArgumentTypes(originalDescriptor), Type.getObjectType("kotlin/coroutines/Continuation")) .joinToString(prefix = "(", postfix = ")", separator = "") + AsmTypes.OBJECT_TYPE else originalDescriptor - return classFileContainsMethod(classId, context.state, Method(name, descriptor)) + return classFileContainsMethod(classId, context.state, Method(function.name.asString(), descriptor)) } val IrMemberWithContainerSource.parentClassId: ClassId? diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt index 275c1d664ad..629179bf7c9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/inlineclasses/MemoizedInlineClassReplacements.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface +import org.jetbrains.kotlin.backend.jvm.codegen.parentClassId import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault import org.jetbrains.kotlin.backend.jvm.ir.isFromJava import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement @@ -226,6 +227,27 @@ class MemoizedInlineClassReplacements( replacementOrigin: IrDeclarationOrigin, noFakeOverride: Boolean = false, body: IrFunction.() -> Unit + ): IrSimpleFunction { + val useOldManglingScheme = context.state.useOldManglingSchemeForFunctionsWithInlineClassesInSignatures + val replacement = buildReplacementInner(function, replacementOrigin, noFakeOverride, useOldManglingScheme, body) + // When using the new mangling scheme we might run into dependencies using the old scheme + // for which we will fall back to the old mangling scheme as well. + if ( + !useOldManglingScheme && + replacement.name.asString().contains("-") && + function.parentClassId?.let { classFileContainsMethod(it, replacement, context) } == false + ) { + return buildReplacementInner(function, replacementOrigin, noFakeOverride, true, body) + } + return replacement + } + + private fun buildReplacementInner( + function: IrFunction, + replacementOrigin: IrDeclarationOrigin, + noFakeOverride: Boolean, + useOldManglingScheme: Boolean, + body: IrFunction.() -> Unit, ): IrSimpleFunction = irFactory.buildFun { updateFrom(function) if (function is IrConstructor) { @@ -243,15 +265,7 @@ class MemoizedInlineClassReplacements( if (noFakeOverride) { isFakeOverride = false } - val useOldManglingScheme = context.state.useOldManglingSchemeForFunctionsWithInlineClassesInSignatures name = mangledNameFor(function, mangleReturnTypes, useOldManglingScheme) - if ( - !useOldManglingScheme && - name.asString().contains("-") && - classFileContainsMethod(function, context, name.asString()) == false - ) { - name = mangledNameFor(function, mangleReturnTypes, true) - } returnType = function.returnType }.apply { parent = function.parent diff --git a/compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt b/compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt new file mode 100644 index 00000000000..d3e0401dfb0 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt @@ -0,0 +1,11 @@ +// FILE: A.kt + +inline class A(val x: String) { + inline fun f(other: A): A = other +} + +// FILE: B.kt + +fun box(): String { + return A("Fail").f(A("OK")).x +} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java index 2d276cffd97..d9f5dee2663 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/CompileKotlinAgainstKotlinTestGenerated.java @@ -164,6 +164,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); } + @TestMetadata("inlineClassInlineFunctionCall.kt") + public void testInlineClassInlineFunctionCall() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt"); + } + @TestMetadata("inlineClassInlineProperty.kt") public void testInlineClassInlineProperty() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java index ce8d71d23cb..cd49136a2cb 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstKotlinTestGenerated.java @@ -165,6 +165,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); } + @TestMetadata("inlineClassInlineFunctionCall.kt") + public void testInlineClassInlineFunctionCall() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt"); + } + @TestMetadata("inlineClassInlineProperty.kt") public void testInlineClassInlineProperty() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java index bc6896c17b6..1e15624f388 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxTestGenerated.java @@ -165,6 +165,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); } + @TestMetadata("inlineClassInlineFunctionCall.kt") + public void testInlineClassInlineFunctionCall() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt"); + } + @TestMetadata("inlineClassInlineProperty.kt") public void testInlineClassInlineProperty() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java index 726aa293ae4..e8b8722bf95 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxTestGenerated.java @@ -165,6 +165,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); } + @TestMetadata("inlineClassInlineFunctionCall.kt") + public void testInlineClassInlineFunctionCall() throws Exception { + runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt"); + } + @TestMetadata("inlineClassInlineProperty.kt") public void testInlineClassInlineProperty() throws Exception { runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt");