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 c7d6c1677a0..f7158989903 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 @@ -10485,6 +10485,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionWithJumpOut.kt"); } + @Test + @TestMetadata("suspendInlineReference.kt") + public void testSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + @Test @TestMetadata("suspendJavaOverrides.kt") public void testSuspendJavaOverrides() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt index 28daa9c6792..bdf4bd0e6b1 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt @@ -313,10 +313,12 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower val result = mutableListOf(view) if (function.body == null || !function.hasContinuation()) return result - // This is a suspend function inside of SAM adapter. - // The attribute of function reference is used for the SAM adapter. - // So, we hack new attributes for continuation class. - if (function.parentAsClass.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL) { + // Sometimes, suspend methods of SAM adapters or function references require a continuation class. + // However, the attribute owner is used to store the name of the SAM adapter or the function reference itself. + // So here we add a local class name using the suspend method itself as the key. + if (function.parentAsClass.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL || + function.parentAsClass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL + ) { context.putLocalClassType( function.attributeOwnerId, Type.getObjectType("${context.getLocalClassType(function.parentAsClass)!!.internalName}$${function.name}$1") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrCoroutineUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrCoroutineUtils.kt index fd2412c7b3b..aac978bbcc6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrCoroutineUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrCoroutineUtils.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrGetField import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.util.functions @@ -36,6 +37,10 @@ fun IrFunction.isInvokeSuspendOfContinuation(): Boolean = private fun IrFunction.isInvokeOfSuspendCallableReference(): Boolean = isSuspend && name.asString().let { name -> name == "invoke" || name.startsWith("invoke-") } && parentAsClass.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL + // References to inline functions don't count since they're not really *references* - the contents + // of the inline function are copy-pasted into the `invoke` method, and may require a continuation. + // (TODO: maybe the reference itself should be the continuation, just like lambdas?) + && (parentAsClass.attributeOwnerId as? IrFunctionReference)?.symbol?.owner?.isInline != true private fun IrFunction.isBridgeToSuspendImplMethod(): Boolean = isSuspend && this is IrSimpleFunction && (parent as? IrClass)?.functions?.any { diff --git a/compiler/testData/codegen/box/coroutines/suspendInlineReference.kt b/compiler/testData/codegen/box/coroutines/suspendInlineReference.kt new file mode 100644 index 00000000000..5d28a52f52a --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/suspendInlineReference.kt @@ -0,0 +1,25 @@ +// WITH_STDLIB +// WITH_COROUTINES +// IGNORE_BACKEND: JVM, JS +import helpers.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +suspend fun suspendHere() = suspendCoroutineUninterceptedOrReturn { + it.resume(Unit) + COROUTINE_SUSPENDED +} + +suspend inline fun foo(): String { + suspendHere() + return "OK" +} + +fun box(): String { + var result = "" + suspend { + val ref = ::foo + result = ref() + }.startCoroutine(EmptyContinuation) + return result +} 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 e28868e8c37..ce714d7ff71 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 @@ -10365,6 +10365,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionWithJumpOut.kt"); } + @Test + @TestMetadata("suspendInlineReference.kt") + public void testSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + @Test @TestMetadata("suspendJavaOverrides.kt") public void testSuspendJavaOverrides() 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 5cb4fc67d50..3b6d846036f 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 @@ -10485,6 +10485,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionWithJumpOut.kt"); } + @Test + @TestMetadata("suspendInlineReference.kt") + public void testSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + @Test @TestMetadata("suspendJavaOverrides.kt") public void testSuspendJavaOverrides() 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 459ab5be8ae..6d4c04ff5cd 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7566,6 +7566,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/suspendFunctionAsSupertype.kt"); } + @TestMetadata("suspendInlineReference.kt") + public void ignoreSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java index 14a7d78bd4b..3f413fe87cf 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java @@ -7433,6 +7433,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionWithJumpOut.kt"); } + @Test + @TestMetadata("suspendInlineReference.kt") + public void testSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + @Test @TestMetadata("suspendLambdaInInterface.kt") public void testSuspendLambdaInInterface() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index 1a8225fb53d..85c0ad5b8a0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -7475,6 +7475,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionWithJumpOut.kt"); } + @Test + @TestMetadata("suspendInlineReference.kt") + public void testSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + @Test @TestMetadata("suspendLambdaInInterface.kt") public void testSuspendLambdaInInterface() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 80f7493bfee..79b9f4aad8b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -6564,6 +6564,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionWithJumpOut.kt"); } + @TestMetadata("suspendInlineReference.kt") + public void testSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + @TestMetadata("suspendLambdaInInterface.kt") public void testSuspendLambdaInInterface() throws Exception { runTest("compiler/testData/codegen/box/coroutines/suspendLambdaInInterface.kt"); diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java index 527d9deb807..5e416496798 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java @@ -8317,6 +8317,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest runTest("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstructionWithJumpOut.kt"); } + @Test + @TestMetadata("suspendInlineReference.kt") + public void testSuspendInlineReference() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/suspendInlineReference.kt"); + } + @Test @TestMetadata("suspendLambdaInInterface.kt") public void testSuspendLambdaInInterface() throws Exception {