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.
This commit is contained in:
Steven Schäfer
2021-01-20 12:57:18 +01:00
committed by Ilmir Usmanov
parent 91717cdcdd
commit 9c4f8f7e54
8 changed files with 60 additions and 11 deletions
@@ -165,6 +165,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
} }
@TestMetadata("inlineClassInlineFunctionCall.kt")
public void testInlineClassInlineFunctionCall() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt");
}
@TestMetadata("inlineClassInlineProperty.kt") @TestMetadata("inlineClassInlineProperty.kt")
public void testInlineClassInlineProperty() throws Exception { public void testInlineClassInlineProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt");
@@ -382,14 +382,13 @@ val IrMemberAccessExpression<*>.psiElement: PsiElement?
fun IrSimpleType.isRawType(): Boolean = fun IrSimpleType.isRawType(): Boolean =
hasAnnotation(JvmGeneratorExtensions.RAW_TYPE_ANNOTATION_FQ_NAME) hasAnnotation(JvmGeneratorExtensions.RAW_TYPE_ANNOTATION_FQ_NAME)
internal fun classFileContainsMethod(function: IrFunction, context: JvmBackendContext, name: String): Boolean? { internal fun classFileContainsMethod(classId: ClassId, function: IrFunction, context: JvmBackendContext): Boolean? {
val classId = function.parentClassId ?: return null
val originalDescriptor = context.methodSignatureMapper.mapSignatureWithGeneric(function).asmMethod.descriptor val originalDescriptor = context.methodSignatureMapper.mapSignatureWithGeneric(function).asmMethod.descriptor
val descriptor = if (function.isSuspend) val descriptor = if (function.isSuspend)
listOf(*Type.getArgumentTypes(originalDescriptor), Type.getObjectType("kotlin/coroutines/Continuation")) listOf(*Type.getArgumentTypes(originalDescriptor), Type.getObjectType("kotlin/coroutines/Continuation"))
.joinToString(prefix = "(", postfix = ")", separator = "") + AsmTypes.OBJECT_TYPE .joinToString(prefix = "(", postfix = ")", separator = "") + AsmTypes.OBJECT_TYPE
else originalDescriptor else originalDescriptor
return classFileContainsMethod(classId, context.state, Method(name, descriptor)) return classFileContainsMethod(classId, context.state, Method(function.name.asString(), descriptor))
} }
val IrMemberWithContainerSource.parentClassId: ClassId? val IrMemberWithContainerSource.parentClassId: ClassId?
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface 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.isCompiledToJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.isFromJava import org.jetbrains.kotlin.backend.jvm.ir.isFromJava
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
@@ -226,6 +227,27 @@ class MemoizedInlineClassReplacements(
replacementOrigin: IrDeclarationOrigin, replacementOrigin: IrDeclarationOrigin,
noFakeOverride: Boolean = false, noFakeOverride: Boolean = false,
body: IrFunction.() -> Unit 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 { ): IrSimpleFunction = irFactory.buildFun {
updateFrom(function) updateFrom(function)
if (function is IrConstructor) { if (function is IrConstructor) {
@@ -243,15 +265,7 @@ class MemoizedInlineClassReplacements(
if (noFakeOverride) { if (noFakeOverride) {
isFakeOverride = false isFakeOverride = false
} }
val useOldManglingScheme = context.state.useOldManglingSchemeForFunctionsWithInlineClassesInSignatures
name = mangledNameFor(function, mangleReturnTypes, useOldManglingScheme) name = mangledNameFor(function, mangleReturnTypes, useOldManglingScheme)
if (
!useOldManglingScheme &&
name.asString().contains("-") &&
classFileContainsMethod(function, context, name.asString()) == false
) {
name = mangledNameFor(function, mangleReturnTypes, true)
}
returnType = function.returnType returnType = function.returnType
}.apply { }.apply {
parent = function.parent parent = function.parent
@@ -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
}
@@ -164,6 +164,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
} }
@TestMetadata("inlineClassInlineFunctionCall.kt")
public void testInlineClassInlineFunctionCall() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt");
}
@TestMetadata("inlineClassInlineProperty.kt") @TestMetadata("inlineClassInlineProperty.kt")
public void testInlineClassInlineProperty() throws Exception { public void testInlineClassInlineProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt");
@@ -165,6 +165,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
} }
@TestMetadata("inlineClassInlineFunctionCall.kt")
public void testInlineClassInlineFunctionCall() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt");
}
@TestMetadata("inlineClassInlineProperty.kt") @TestMetadata("inlineClassInlineProperty.kt")
public void testInlineClassInlineProperty() throws Exception { public void testInlineClassInlineProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt");
@@ -165,6 +165,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
} }
@TestMetadata("inlineClassInlineFunctionCall.kt")
public void testInlineClassInlineFunctionCall() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt");
}
@TestMetadata("inlineClassInlineProperty.kt") @TestMetadata("inlineClassInlineProperty.kt")
public void testInlineClassInlineProperty() throws Exception { public void testInlineClassInlineProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt");
@@ -165,6 +165,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassFromBinaryDependencies.kt");
} }
@TestMetadata("inlineClassInlineFunctionCall.kt")
public void testInlineClassInlineFunctionCall() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineFunctionCall.kt");
}
@TestMetadata("inlineClassInlineProperty.kt") @TestMetadata("inlineClassInlineProperty.kt")
public void testInlineClassInlineProperty() throws Exception { public void testInlineClassInlineProperty() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt"); runTest("compiler/testData/compileKotlinAgainstKotlin/inlineClassInlineProperty.kt");