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 f6c0dbafab4..3ee901fabc2 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 @@ -10643,6 +10643,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testReturnResult() throws Exception { runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt"); } + + @Test + @TestMetadata("syntheticAccessor.kt") + public void testSyntheticAccessor() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt"); + } } @Nested diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index 3402469f560..481b6fb9609 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_IMPL_NAME_SUFFIX import org.jetbrains.kotlin.codegen.coroutines.reportSuspensionPointInsideMonitor -import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET @@ -142,16 +141,19 @@ private fun IrFunction.isStaticInlineClassReplacementDelegatingCall(): Boolean = parentAsClass.declarations.find { it is IrAttributeContainer && it.attributeOwnerId == attributeOwnerId && it !== this } ?.isStaticInlineClassReplacement == true -internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspendOfContinuation() && - // These are tail-call bridges and do not require any bytecode modifications. - origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && - origin != JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER && - origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR && - origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR && - origin != JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE && - origin != IrDeclarationOrigin.BRIDGE && - origin != IrDeclarationOrigin.BRIDGE_SPECIAL && +internal val BRIDGE_ORIGINS = setOf( + IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, + JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER, + JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR, + JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR, + JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE, + IrDeclarationOrigin.BRIDGE, + IrDeclarationOrigin.BRIDGE_SPECIAL, +) + +internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = origin !in BRIDGE_ORIGINS && origin != IrDeclarationOrigin.DELEGATED_MEMBER && + !isInvokeSuspendOfContinuation() && !isMultifileBridge() && !isInvokeOfSuspendCallableReference() && !isBridgeToSuspendImplMethod() && diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 27f506abd77..6c477207e21 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -229,20 +229,17 @@ class ExpressionCodegen( if (irFunction.origin != JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER) { irFunction.markLineNumber(startOffset = irFunction is IrConstructor && irFunction.isPrimary) } - if (irFunction.isSuspend && irFunction.origin == IrDeclarationOrigin.BRIDGE) { - mv.areturn(OBJECT_TYPE) + val unboxedInlineClass = + irFunction.suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass() + if (unboxedInlineClass != null && irFunction.origin !in BRIDGE_ORIGINS) { + result.materializeAt(unboxedInlineClass.asmType, unboxedInlineClass) } else { - var returnType = signature.returnType - var returnIrType = if (irFunction !is IrConstructor) irFunction.returnType else context.irBuiltIns.unitType - val unboxedInlineClass = - irFunction.suspendFunctionOriginal().originalReturnTypeOfSuspendFunctionReturningUnboxedInlineClass() - if (unboxedInlineClass != null) { - returnIrType = unboxedInlineClass - returnType = unboxedInlineClass.asmType - } - result.materializeAt(returnType, returnIrType) - mv.areturn(returnType) + val returnIrType = if (irFunction !is IrConstructor) irFunction.returnType else context.irBuiltIns.unitType + result.materializeAt(signature.returnType, returnIrType) } + // `signature.returnType` is valid here even if the return value of a suspend function was unboxed, + // as it's still a reference type. + mv.areturn(signature.returnType) } val endLabel = markNewLabel() writeLocalVariablesInTable(info, endLabel) @@ -508,7 +505,7 @@ class ExpressionCodegen( wrapJavaClassesIntoKClasses(mv) MaterialValue(this, AsmTypes.K_CLASS_ARRAY_TYPE, expression.type) } - unboxedInlineClassIrType != null && !irFunction.isInvokeSuspendOfContinuation() -> + unboxedInlineClassIrType != null && !irFunction.isInvokeSuspendOfContinuation() && irFunction.origin !in BRIDGE_ORIGINS -> object : PromisedValue(this, unboxedInlineClassIrType.asmType, unboxedInlineClassIrType) { override fun materializeAt(target: Type, irTarget: IrType, castForReified: Boolean) { mv.checkcast(unboxedInlineClassIrType.asmType) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index d70b6eda1ca..512ecc231d4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -416,7 +416,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle isSuspend = source.isSuspend // synthetic accessors of suspend functions are handled in codegen }.also { accessor -> accessor.parent = parent - + accessor.copyAttributes(source) accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR, dispatchReceiverType) accessor.returnType = source.returnType.remapTypeParameters(source, accessor) diff --git a/compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt b/compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt new file mode 100644 index 00000000000..7ceb04aaf7b --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt @@ -0,0 +1,29 @@ +// WITH_RUNTIME +// WITH_COROUTINES + +import helpers.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +@Suppress("UNSUPPORTED_FEATURE") +inline class I(val x: Any?) + +suspend fun suspendHere(): Unit = suspendCoroutineUninterceptedOrReturn { c -> + c.resume(Unit) + COROUTINE_SUSPENDED +} + +class C { + private suspend fun f(): I { + suspendHere() + return I("OK") + } + + fun g() = suspend { f() } +} + +fun box(): String { + var result = "fail" + suspend { result = C().g()().x as String }.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 edbbe2b3cc7..79dd1be7141 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 @@ -10643,6 +10643,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testReturnResult() throws Exception { runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt"); } + + @Test + @TestMetadata("syntheticAccessor.kt") + public void testSyntheticAccessor() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt"); + } } @Nested 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 14aeea519b4..fe05eb49c43 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 @@ -10643,6 +10643,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testReturnResult() throws Exception { runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt"); } + + @Test + @TestMetadata("syntheticAccessor.kt") + public void testSyntheticAccessor() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt"); + } } @Nested diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index bfee0747e1c..59883302a2a 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -8448,6 +8448,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testReturnResult() throws Exception { runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt"); } + + @TestMetadata("syntheticAccessor.kt") + public void testSyntheticAccessor() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 3f09b682219..62b681270ed 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -7592,6 +7592,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes public void testReturnResult() throws Exception { runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt"); } + + @TestMetadata("syntheticAccessor.kt") + public void testSyntheticAccessor() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index c95b80f830c..0f6a021fb0c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -7003,6 +7003,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testReturnResult() throws Exception { runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt"); } + + @TestMetadata("syntheticAccessor.kt") + public void testSyntheticAccessor() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException") diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 36a78dad8b4..21ea7ee103e 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -7003,6 +7003,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testReturnResult() throws Exception { runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/returnResult.kt"); } + + @TestMetadata("syntheticAccessor.kt") + public void testSyntheticAccessor() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/inlineClasses/resume/syntheticAccessor.kt"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/inlineClasses/resumeWithException")