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
This commit is contained in:
Alexander Udalov
2021-10-01 02:07:00 +02:00
parent 43a83dd07a
commit 31ba7f24b1
6 changed files with 42 additions and 5 deletions
@@ -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 {
@@ -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,
@@ -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.String, kotlin.coroutines.Continuation<? super java.lang.String>, java.lang.Object>, " +
"interface kotlin.coroutines.jvm.internal.SuspendFunction" +
"]"
return if (expected == actual) "OK" else "Fail: $actual"
}
@@ -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 {
@@ -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 {
@@ -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");