From 31ba7f24b1c6702638fe871f52f9dba8af81872a Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 1 Oct 2021 02:07:00 +0200 Subject: [PATCH] JVM IR: fix generic signatures of suspend function references Using `kotlin.jvm.functions.Function{n+1}` (via `getJvmSuspendFunctionClass`) for suspend functions was wrong in the function reference lowering, because we didn't adapt the parameter types by transforming the last type to Continuation and adding Object, and generic signature ended up being incorrect. Actually there was no need to use `kotlin.jvm.functions.Function{n+1}` at all. We can just use the built-in `kotlin.coroutines.SuspendFunction{n}` as a supertype, and it will be mapped correctly later in codegen. It's not even needed to add the `kotlin.coroutines.jvm.internal.SuspendFunction` marker manually, since it's also handled by the codegen (see `IrTypeMapper.mapClassSignature`). #KT-48732 Fixed --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++++++ .../jvm/lower/FunctionReferenceLowering.kt | 7 ++----- .../kt48732_genericSignature.kt | 17 +++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/IrBlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/LightAnalysisModeTestGenerated.java | 5 +++++ 6 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 4374bc62075..ee0015cadb7 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -10464,6 +10464,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); } + @Test + @TestMetadata("kt48732_genericSignature.kt") + public void testKt48732_genericSignature() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt"); + } + @Test @TestMetadata("lambdaParameterUsed.kt") public void testLambdaParameterUsed() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt index bdb45c35dc9..ccdde365c68 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt @@ -380,9 +380,9 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) private val functionSuperClass = samSuperType?.classOrNull ?: if (irFunctionReference.isSuspend) - context.ir.symbols.getJvmSuspendFunctionClass(argumentTypes.size) + context.irBuiltIns.suspendFunctionN(argumentTypes.size).symbol else - context.ir.symbols.getJvmFunctionClass(argumentTypes.size) + context.irBuiltIns.functionN(argumentTypes.size).symbol private val superMethod = functionSuperClass.owner.getSingleAbstractMethod() ?: throw AssertionError("Not a SAM class: ${functionSuperClass.owner.render()}") @@ -445,9 +445,6 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) if (samSuperType == null) functionSuperClass.typeWith(parameterTypes) else null, - if (irFunctionReference.isSuspend) - context.ir.symbols.suspendFunctionInterface.defaultType - else null, if (needToGenerateSamEqualsHashCodeMethods) context.ir.symbols.functionAdapter.defaultType else null, diff --git a/compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt b/compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt new file mode 100644 index 00000000000..d6493b40cc5 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt @@ -0,0 +1,17 @@ +// TARGET_BACKEND: JVM +// WITH_COROUTINES +// WITH_RUNTIME + +suspend fun id(x: String): String = x + +val f: suspend (String) -> String = ::id + +fun box(): String { + val actual = f.javaClass.genericInterfaces.toList().toString() + val expected = "[" + + "kotlin.jvm.functions.Function2, java.lang.Object>, " + + "interface kotlin.coroutines.jvm.internal.SuspendFunction" + + "]" + + return if (expected == actual) "OK" else "Fail: $actual" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 9b96a08b5ee..90da13c7af2 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -10386,6 +10386,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); } + @Test + @TestMetadata("kt48732_genericSignature.kt") + public void testKt48732_genericSignature() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt"); + } + @Test @TestMetadata("lambdaParameterUsed.kt") public void testLambdaParameterUsed() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 6b95a1d2f73..eae9d1cc442 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -10464,6 +10464,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); } + @Test + @TestMetadata("kt48732_genericSignature.kt") + public void testKt48732_genericSignature() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt"); + } + @Test @TestMetadata("lambdaParameterUsed.kt") public void testLambdaParameterUsed() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 5f2cabffdd6..90e2fda0bfc 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -8191,6 +8191,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/fromJava.kt"); } + @TestMetadata("kt48732_genericSignature.kt") + public void testKt48732_genericSignature() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/kt48732_genericSignature.kt"); + } + @TestMetadata("lambdaParameterUsed.kt") public void testLambdaParameterUsed() throws Exception { runTest("compiler/testData/codegen/box/coroutines/featureIntersection/callableReference/lambdaParameterUsed.kt");