diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 6a4ac6986c1..8fd95b9ae79 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt index 1236644d2a9..d7e121760d6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.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>() 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)) diff --git a/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt b/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt index d68dbd4b957..ec496236572 100644 --- a/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt +++ b/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/bound.kt @@ -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) } diff --git a/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt b/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt new file mode 100644 index 00000000000..9274074db21 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/boundExtension.kt @@ -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 +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/inlineBound.kt b/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/inlineBound.kt index 0b7bc0aac86..a45b389582c 100644 --- a/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/inlineBound.kt +++ b/compiler/testData/codegen/box/callableReference/adaptedReferences/suspendConversion/inlineBound.kt @@ -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) } diff --git a/compiler/testData/codegen/box/callableReference/equality/suspendConversion.kt b/compiler/testData/codegen/box/callableReference/equality/suspendConversion.kt index 91c255c3d2d..fa4a85ecd02 100644 --- a/compiler/testData/codegen/box/callableReference/equality/suspendConversion.kt +++ b/compiler/testData/codegen/box/callableReference/equality/suspendConversion.kt @@ -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) { diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 9488eb8e37e..a028a2c1375 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 70357c56953..164c0f4679c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index c96b47f0841..61a12a1cbef 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index e677dfb5c98..73a353dc16e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -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"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 3fd1139780a..af695fcad09 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -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"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 881cd08d835..0e422c9defa 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -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");