JVM_IR: fix bound suspend-converted references

Note: inlining of adapted callable references is still suboptimal.

 #KT-42021 Fixed
This commit is contained in:
pyos
2020-09-22 11:53:29 +02:00
committed by max-kammerer
parent ac50433e17
commit 0e8a664c9b
12 changed files with 69 additions and 14 deletions
@@ -2207,6 +2207,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt");
}
@TestMetadata("boundExtension.kt")
public void testBoundExtension() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt");
}
@TestMetadata("crossInline.kt")
public void testCrossInline() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/crossInline.kt");
@@ -41,14 +41,20 @@ internal val functionReferencePhase = makeIrFilePhase(
)
internal class FunctionReferenceLowering(private val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
// This pass ignores suspend function references and function references used in inline arguments to inline functions.
// This pass ignores function references used as inline arguments. `InlineCallableReferenceToLambdaPhase`
// converts them into lambdas instead, so that after inlining there is only a direct call left, with no
// function reference classes needed.
private val ignoredFunctionReferences = mutableSetOf<IrCallableReference<*>>()
private val IrFunctionReference.isIgnored: Boolean
get() = (!type.isFunctionOrKFunction() || ignoredFunctionReferences.contains(this)) && !isSuspendFunctionReference()
get() = (!type.isFunctionOrKFunction() && !isSuspendFunctionReference()) || ignoredFunctionReferences.contains(this)
// TODO: Currently, origin of callable references is null. Do we need to create one?
private fun IrFunctionReference.isSuspendFunctionReference(): Boolean = isSuspend && origin == null
// `suspend` function references are the same as non-`suspend` ones, just with a `suspend` invoke;
// however, suspending lambdas require different generation implemented in AddContinuationLowering
// because they are also their own continuation classes.
// TODO: Currently, origin of callable references explicitly written in source code is null. Do we need to create one?
private fun IrFunctionReference.isSuspendFunctionReference(): Boolean = isSuspend &&
(origin == null || origin == IrStatementOrigin.ADAPTED_FUNCTION_REFERENCE)
override fun lower(irFile: IrFile) {
ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile))
@@ -1,14 +1,10 @@
// !LANGUAGE: +SuspendConversion
// WITH_RUNTIME
// WITH_COROUTINES
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
fun runSuspend(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
@@ -0,0 +1,24 @@
// !LANGUAGE: +SuspendConversion
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
fun runSuspend(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
class C {
var test = "failed"
}
fun C.foo() {
test = "OK"
}
fun box(): String {
val c = C()
runSuspend(c::foo)
return c.test
}
@@ -1,14 +1,10 @@
// !LANGUAGE: +SuspendConversion
// WITH_RUNTIME
// WITH_COROUTINES
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
fun runSuspend(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
@@ -1,7 +1,5 @@
// !LANGUAGE: +SuspendConversion
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// ^ TODO fix suspend coercion for bound function references in JVM_IR
// FILE: suspendCovnersion.kt
fun checkNotEqual(x: Any, y: Any) {
@@ -2227,6 +2227,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt");
}
@TestMetadata("boundExtension.kt")
public void testBoundExtension() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt");
}
@TestMetadata("crossInline.kt")
public void testCrossInline() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/crossInline.kt");
@@ -2227,6 +2227,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt");
}
@TestMetadata("boundExtension.kt")
public void testBoundExtension() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt");
}
@TestMetadata("crossInline.kt")
public void testCrossInline() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/crossInline.kt");
@@ -2207,6 +2207,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt");
}
@TestMetadata("boundExtension.kt")
public void testBoundExtension() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt");
}
@TestMetadata("crossInline.kt")
public void testCrossInline() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/crossInline.kt");
@@ -1612,6 +1612,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt");
}
@TestMetadata("boundExtension.kt")
public void testBoundExtension() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt");
}
@TestMetadata("crossInline.kt")
public void testCrossInline() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/crossInline.kt");
@@ -1612,6 +1612,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt");
}
@TestMetadata("boundExtension.kt")
public void testBoundExtension() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt");
}
@TestMetadata("crossInline.kt")
public void testCrossInline() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/crossInline.kt");
@@ -1612,6 +1612,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt");
}
@TestMetadata("boundExtension.kt")
public void testBoundExtension() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt");
}
@TestMetadata("crossInline.kt")
public void testCrossInline() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/crossInline.kt");