FIC: support suspend conversions in jvm codegen

This commit is contained in:
Mikhail Zarechenskiy
2019-12-17 16:27:44 +03:00
parent b98d8bd7c1
commit 70094884ca
8 changed files with 55 additions and 4 deletions
@@ -230,6 +230,8 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
erasedInterfaceFunction.getValueParameters(), erasedInterfaceFunction.getReturnType(),
Modality.OPEN, erasedInterfaceFunction.getVisibility());
descriptorForBridges.setSuspend(descriptor.isSuspend());
DescriptorUtilsKt.setSingleOverridden(descriptorForBridges, erasedInterfaceFunction);
codegen.generateBridges(descriptorForBridges);
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen.coroutines
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalClassDescriptor
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
@@ -263,7 +264,7 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
annotations = Annotations.EMPTY,
name = CONTINUATION_PARAMETER_NAME,
// Add j.l.Object to invoke(), because that is the type of parameters we have in FunctionN+1
outType = if (function.containingDeclaration.safeAs<ClassDescriptor>()?.defaultType?.isBuiltinFunctionalType == true)
outType = if (function.containingDeclaration.safeAs<ClassDescriptor>()?.isBuiltinFunctionalClassDescriptor == true)
function.builtIns.nullableAnyType
else
function.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines),
@@ -0,0 +1,25 @@
// !LANGUAGE: +NewInference +FunctionInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// WITH_COROUTINES
// WITH_RUNTIME
import helpers.*
import kotlin.coroutines.startCoroutine
fun interface SuspendRunnable {
suspend fun invoke()
}
fun run(r: SuspendRunnable) {
r::invoke.startCoroutine(EmptyContinuation)
}
var result = "initial"
suspend fun bar() {
result = "OK"
}
fun box(): String {
run(::bar)
return result
}
@@ -11656,6 +11656,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testReceiverEvaluatedOnce() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
}
@TestMetadata("suspendFunInterfaceConversionCodegen.kt")
public void testSuspendFunInterfaceConversionCodegen() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/functions")
@@ -11656,6 +11656,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
public void testReceiverEvaluatedOnce() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
}
@TestMetadata("suspendFunInterfaceConversionCodegen.kt")
public void testSuspendFunInterfaceConversionCodegen() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/functions")
@@ -10506,6 +10506,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
public void testReceiverEvaluatedOnce() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
}
@TestMetadata("suspendFunInterfaceConversionCodegen.kt")
public void testSuspendFunInterfaceConversionCodegen() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/functions")
@@ -10506,6 +10506,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
public void testReceiverEvaluatedOnce() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
}
@TestMetadata("suspendFunInterfaceConversionCodegen.kt")
public void testSuspendFunInterfaceConversionCodegen() throws Exception {
runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/functions")
@@ -65,10 +65,13 @@ val KotlinType.isFunctionOrSuspendFunctionType: Boolean
get() = isFunctionType || isSuspendFunctionType
val KotlinType.isBuiltinFunctionalType: Boolean
get() = constructor.declarationDescriptor?.isBuiltinFunctionalClassDescriptor == true
val DeclarationDescriptor.isBuiltinFunctionalClassDescriptor: Boolean
get() {
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
return kind == FunctionClassDescriptor.Kind.Function ||
kind == FunctionClassDescriptor.Kind.SuspendFunction
val functionalClassKind = getFunctionalClassKind()
return functionalClassKind == FunctionClassDescriptor.Kind.Function ||
functionalClassKind == FunctionClassDescriptor.Kind.SuspendFunction
}
fun isBuiltinFunctionClass(classId: ClassId): Boolean {