diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index aada5c22e97..a638ce51f40 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2810,7 +2810,7 @@ public class ExpressionCodegen extends KtVisitor impleme if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext)) { // Suspension points should behave like they leave actual values on stack, while real methods return VOID - return new OperationStackValue(getSuspensionReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda()); + return new OperationStackValue(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda()); } return result; @@ -2925,7 +2925,7 @@ public class ExpressionCodegen extends KtVisitor impleme } if (isSuspensionPoint) { - v.tconst(getSuspensionReturnTypeByResolvedCall(resolvedCall)); + v.tconst(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall)); v.invokestatic( CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER, CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME, @@ -2935,7 +2935,6 @@ public class ExpressionCodegen extends KtVisitor impleme callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this); if (isSuspensionPoint) { - AsmUtil.pushDefaultValueOnStack(getSuspensionReturnTypeByResolvedCall(resolvedCall), v); v.invokestatic( CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER, CoroutineCodegenUtilKt.AFTER_SUSPENSION_POINT_MARKER_NAME, "()V", false); @@ -2950,7 +2949,7 @@ public class ExpressionCodegen extends KtVisitor impleme } @NotNull - private Type getSuspensionReturnTypeByResolvedCall(@NotNull ResolvedCall resolvedCall) { + private Type getSuspensionBoxedReturnTypeByResolvedCall(@NotNull ResolvedCall resolvedCall) { assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor : "Suspension point resolved call should be built on SimpleFunctionDescriptor"; @@ -2963,7 +2962,7 @@ public class ExpressionCodegen extends KtVisitor impleme KotlinType returnType = initialSignature.getReturnType(); assert returnType != null : "Return type of suspension point should not be null"; - return typeMapper.mapType(returnType); + return typeMapper.mapType(TypeUtils.makeNullable(returnType)); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt index 1b29c6b7eb1..ad8c7275180 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue import org.jetbrains.kotlin.codegen.optimization.common.analyzeLiveness import org.jetbrains.kotlin.codegen.optimization.common.insnListOf import org.jetbrains.kotlin.codegen.optimization.common.removeEmptyCatchBlocks +import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.utils.sure @@ -95,8 +96,10 @@ class CoroutineTransformerMethodVisitor( spillVariables(suspensionPoints, methodNode) + val suspendMarkerVarIndex = methodNode.maxLocals++ + val suspensionPointLabels = suspensionPoints.withIndex().map { - transformCallAndReturnContinuationLabel(it.index + 1, it.value, methodNode) + transformCallAndReturnContinuationLabel(it.index + 1, it.value, methodNode, suspendMarkerVarIndex) } methodNode.instructions.apply { @@ -116,6 +119,13 @@ class CoroutineTransformerMethodVisitor( // tableswitch(this.label) insertBefore(firstToInsertBefore, insnListOf( + FieldInsnNode( + Opcodes.GETSTATIC, + AsmTypes.COROUTINES_SUSPEND.internalName, + JvmAbi.INSTANCE_FIELD, + AsmTypes.COROUTINES_SUSPEND.descriptor + ), + VarInsnNode(Opcodes.ASTORE, suspendMarkerVarIndex), VarInsnNode(Opcodes.ALOAD, 0), FieldInsnNode( Opcodes.GETFIELD, @@ -178,20 +188,16 @@ class CoroutineTransformerMethodVisitor( methodNode.instructions.remove(beforeSuspensionPointMarker.previous) beforeSuspensionPointMarker.desc = "()V" - if (suspensionPoint.returnType != Type.VOID_TYPE) { - val previous = suspensionPoint.suspensionCallEnd.previous - assert(previous.opcode in DEFAULT_VALUE_OPCODES) { - "Expected on of default value bytecodes, but ${previous.opcode} was found" - } - fakeReturnValueInsns.add(previous) + assert(suspensionPoint.returnType != Type.VOID_TYPE) { "Suspension point can't be VOID" } - if (previous.opcode == Opcodes.ACONST_NULL) { - // Checkcast is needed to tell analyzer what type exactly should be returned from suspension point - val checkCast = TypeInsnNode(Opcodes.CHECKCAST, suspensionPoint.returnType.internalName) - methodNode.instructions.insert(previous, checkCast) - fakeReturnValueInsns.add(checkCast) - } - } + // Checkcast only is needed to tell analyzer what type exactly should be returned from suspension point + // This type is used when for restoring spilled variables into fields + val checkCast = TypeInsnNode(Opcodes.CHECKCAST, suspensionPoint.returnType.internalName) + methodNode.instructions.insertBefore( + suspensionPoint.suspensionCallEnd, checkCast + ) + + fakeReturnValueInsns.add(checkCast) } } } @@ -317,8 +323,14 @@ class CoroutineTransformerMethodVisitor( return suspensionCallEnd.next as LabelNode } - private fun transformCallAndReturnContinuationLabel(id: Int, suspension: SuspensionPoint, methodNode: MethodNode): LabelNode { + private fun transformCallAndReturnContinuationLabel( + id: Int, + suspension: SuspensionPoint, + methodNode: MethodNode, + suspendMarkerVarIndex: Int + ): LabelNode { val continuationLabel = LabelNode() + val continuationLabelAfterLoadedResult = LabelNode() with(methodNode.instructions) { // Save state insertBefore(suspension.suspensionCallBegin, @@ -336,6 +348,10 @@ class CoroutineTransformerMethodVisitor( suspension.fakeReturnValueInsns.forEach { methodNode.instructions.remove(it) } insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter { + dup() + load(suspendMarkerVarIndex, AsmTypes.COROUTINES_SUSPEND) + ifacmpne(continuationLabelAfterLoadedResult.label) + // Exit areturn(Type.VOID_TYPE) // Mark place for continuation @@ -358,6 +374,8 @@ class CoroutineTransformerMethodVisitor( // Load continuation argument just like suspending function returns it load(1, AsmTypes.OBJECT_TYPE) + + visitLabel(continuationLabelAfterLoadedResult.label) StackValue.coerce(AsmTypes.OBJECT_TYPE, suspension.returnType, this) }) } @@ -371,8 +389,7 @@ class CoroutineTransformerMethodVisitor( // How suspension point area will look like after all transformations: // // INVOKESTATIC beforeSuspensionMarker - // INVOKEVIRTUAL suspensionMethod()V - // ACONST_NULL -- default value + // INVOKEVIRTUAL suspensionMethod()Ljava/lang/Object; // CHECKCAST SomeType // INVOKESTATIC afterSuspensionMarker // L1: -- end of all TCB's that are containing the suspension point (inserted by this method) @@ -480,8 +497,7 @@ private fun Type.normalize() = /** * Suspension call may consists of several instructions: * INVOKESTATIC beforeSuspensionMarker - * INVOKEVIRTUAL suspensionMethod()V // actually it could be some inline method instead of plain call - * ACONST_NULL // It's only needed when the suspension point returns something beside VOID + * INVOKEVIRTUAL suspensionMethod()Ljava/lang/Object; // actually it could be some inline method instead of plain call * CHECKCAST Type * INVOKESTATIC afterSuspensionMarker */ diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt index 6a7ebd96bbe..f9bd402028d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -189,7 +189,7 @@ fun ResolvedCall<*>.isSuspensionPoint(bindingContext: BindingContext) = bindingContext[BindingContext.COROUTINE_RECEIVER_FOR_SUSPENSION_POINT, call] != null // Suspend functions have irregular signatures on JVM, containing an additional last parameter with type `Continuation`, -// and return type Unit (later it will be replaced with 'Any?') +// and return type Any? // This function returns a function descriptor reflecting how the suspend function looks from point of view of JVM fun createJvmSuspendFunctionView(function: D): D { val continuationParameter = ValueParameterDescriptorImpl( @@ -201,7 +201,7 @@ fun createJvmSuspendFunctionView(function: D): D { return function.createCustomCopy { setPreserveSourceElement() - setReturnType(function.builtIns.unitType) + setReturnType(function.builtIns.nullableAnyType) setValueParameters(it.valueParameters + continuationParameter) putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, it) } @@ -288,8 +288,7 @@ fun createMethodNodeForSuspendWithCurrentContinuation( "(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}", true ) - node.visitInsn(Opcodes.POP) - node.visitInsn(Opcodes.RETURN) + node.visitInsn(Opcodes.ARETURN) node.visitMaxs(2, 2) return node diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java index b2c5e9b1a24..034839f15a3 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/AsmTypes.java @@ -41,6 +41,7 @@ public class AsmTypes { public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1"); public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2"); public static final Type COROUTINE_IMPL = Type.getObjectType("kotlin/jvm/internal/CoroutineImpl"); + public static final Type COROUTINES_SUSPEND = Type.getObjectType("kotlin/coroutines/Suspend"); public static final Type[] PROPERTY_REFERENCE_IMPL = { diff --git a/compiler/testData/codegen/box/coroutines/beginWithException.kt b/compiler/testData/codegen/box/coroutines/beginWithException.kt index 60bf359bd03..1e8707f9a75 100644 --- a/compiler/testData/codegen/box/coroutines/beginWithException.kt +++ b/compiler/testData/codegen/box/coroutines/beginWithException.kt @@ -7,7 +7,7 @@ class Controller { exception = t } - suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->} + suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x -> } // INTERCEPT_RESUME_PLACEHOLDER } diff --git a/compiler/testData/codegen/box/coroutines/coercionToUnit.kt b/compiler/testData/codegen/box/coroutines/coercionToUnit.kt index f99d19ae132..7a971461ec7 100644 --- a/compiler/testData/codegen/box/coroutines/coercionToUnit.kt +++ b/compiler/testData/codegen/box/coroutines/coercionToUnit.kt @@ -7,6 +7,7 @@ class Controller { suspend fun await(t: T): T = suspendWithCurrentContinuation { c -> c.resume(t) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt b/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt index c6c980ba121..c2c9e3045cb 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt @@ -7,6 +7,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt index 5f16f6ca29a..072350629c0 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt @@ -7,6 +7,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt index cc1cbc3cc06..96d0d087e65 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt @@ -7,6 +7,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt b/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt index 0a5172ff965..15fd6a18ae0 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt @@ -7,6 +7,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt index e7db1a7bf27..ca5cbe28f15 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt @@ -7,6 +7,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt index 29d9c92195f..126f63f8553 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt @@ -7,6 +7,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt b/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt index 5990e3fcbae..1c030209d12 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt @@ -12,6 +12,7 @@ class Controller { suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { c -> result += "suspend($value);" c.resume(value) + Suspend } operator fun handleResult(value: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt b/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt index 23a91960e06..812f77edca5 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt @@ -8,6 +8,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> result += "[" c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt b/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt index 46659139efa..e7e5f821519 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt @@ -8,11 +8,13 @@ class Controller { suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { c -> result += "suspend($value);" c.resume(value) + Suspend } suspend fun suspendLogAndThrow(exception: Throwable): Nothing = suspendWithCurrentContinuation { c -> result += "throw(${exception.message});" c.resumeWithException(exception) + Suspend } operator fun handleException(exception: Throwable, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt index 39c4d7aa2fb..f9fe9d2d65b 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt @@ -8,6 +8,7 @@ class Controller { suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { c -> result += "suspend($value);" c.resume(value) + Suspend } operator fun handleException(exception: Throwable, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt index edba032212d..42c63d03a31 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt @@ -7,6 +7,7 @@ class Controller { suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt b/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt index 18796de9f9a..f13d99d91b4 100644 --- a/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt +++ b/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt @@ -3,6 +3,7 @@ class Controller { var result = false suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } fun foo() { diff --git a/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt b/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt index 13a43901e35..14650e2ddfb 100644 --- a/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt +++ b/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(a: String = "abc", i: Int = 2): String = suspendWithCurrentContinuation { x -> x.resume(a + "#" + (i + 1)) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/emptyClosure.kt b/compiler/testData/codegen/box/coroutines/emptyClosure.kt index 11b0ccae3eb..a197a3b1628 100644 --- a/compiler/testData/codegen/box/coroutines/emptyClosure.kt +++ b/compiler/testData/codegen/box/coroutines/emptyClosure.kt @@ -5,6 +5,7 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> result++ x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt b/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt index 26777cc5ae7..b1c599f5785 100644 --- a/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt +++ b/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(v: T): T = suspendWithCurrentContinuation { x -> x.resume(v) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/generate.kt b/compiler/testData/codegen/box/coroutines/generate.kt index 68208690e9d..1a25bdae98a 100644 --- a/compiler/testData/codegen/box/coroutines/generate.kt +++ b/compiler/testData/codegen/box/coroutines/generate.kt @@ -47,6 +47,8 @@ class GeneratorController() : AbstractIterator() { suspend fun yield(value: T): Unit = suspendWithCurrentContinuation { c -> setNext(value) setNextStep(c) + + Suspend } operator fun handleResult(result: Unit, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/handleException.kt b/compiler/testData/codegen/box/coroutines/handleException.kt index f2173da08e5..8de9ff27255 100644 --- a/compiler/testData/codegen/box/coroutines/handleException.kt +++ b/compiler/testData/codegen/box/coroutines/handleException.kt @@ -8,12 +8,16 @@ class Controller { postponedActions.add { x.resume(v) } + + Suspend } suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } + + Suspend } operator fun handleException(t: Throwable, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt b/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt index d0b6da946c8..c4b1a636583 100644 --- a/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt +++ b/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt @@ -3,6 +3,7 @@ class Controller { var isCompleted = false suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } operator fun handleResult(x: Unit, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt b/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt index 88c0b409be1..3681459a921 100644 --- a/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt +++ b/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt @@ -5,6 +5,7 @@ class Controller { suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { x -> log += "suspend($value);" x.resume(value) + Suspend } operator fun handleResult(value: String, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/illegalState.kt b/compiler/testData/codegen/box/coroutines/illegalState.kt index c5ea8108ca5..e5f9839f1f4 100644 --- a/compiler/testData/codegen/box/coroutines/illegalState.kt +++ b/compiler/testData/codegen/box/coroutines/illegalState.kt @@ -5,6 +5,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } } diff --git a/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt b/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt index 75797f715a5..8362eaff98a 100644 --- a/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt +++ b/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt @@ -11,6 +11,7 @@ class Controller { suspend inline fun suspendInline(v: String): String = suspendWithCurrentContinuation { x -> withValue(v, x) + Suspend } suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b()) diff --git a/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt b/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt index 1eb75978551..82c0407505d 100644 --- a/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt +++ b/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt @@ -9,12 +9,16 @@ class Controller { postponedActions.add { x.resume(v) } + + Suspend } suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } + + Suspend } operator fun handleResult(x: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt b/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt index d00d58c5227..bbc0a579bf9 100644 --- a/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt +++ b/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt @@ -3,6 +3,7 @@ class Controller { var i = 0 suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume((i++).toString()) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt b/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt index 78202e6e94e..402321cd51f 100644 --- a/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt +++ b/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt @@ -6,11 +6,13 @@ class Controller { suspend fun runInstanceOf(): Boolean = suspendWithCurrentContinuation { x -> val y: Any = x x.resume(x is Continuation<*>) + Suspend } suspend fun runCast(): Boolean = suspendWithCurrentContinuation { x -> val y: Any = x x.resume(Continuation::class.isInstance(y as Continuation<*>)) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt index 9a0684a4daa..a6a3163f908 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt index 6d52fc884a0..caf75f8408e 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt index 8ba9949c25d..cb25ba39b8d 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt index 23361d18058..327b4abd55b 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt index 9424876b858..eaa50401ada 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt index 62d703ea88c..7a9dd3c6973 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt index 0ecfc004a00..babbb912f96 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt @@ -4,6 +4,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt index 831fd94fde0..2486215d538 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt index ccb28330e9c..5348122669e 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt @@ -4,6 +4,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt index 076614d8433..3a410ce6ef1 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/iterateOverArray.kt b/compiler/testData/codegen/box/coroutines/iterateOverArray.kt index 8e500113e0e..0013e5070f8 100644 --- a/compiler/testData/codegen/box/coroutines/iterateOverArray.kt +++ b/compiler/testData/codegen/box/coroutines/iterateOverArray.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/kt12958.kt b/compiler/testData/codegen/box/coroutines/kt12958.kt index 16c0e031547..6b94b641c65 100644 --- a/compiler/testData/codegen/box/coroutines/kt12958.kt +++ b/compiler/testData/codegen/box/coroutines/kt12958.kt @@ -3,6 +3,7 @@ class Controller { var result = "fail" suspend fun suspendHere(v: V): V = suspendWithCurrentContinuation { x -> x.resume(v) + Suspend } operator fun handleResult(x: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/lambdaParameters.kt b/compiler/testData/codegen/box/coroutines/lambdaParameters.kt index 538e49ae33f..6b98ead3b6a 100644 --- a/compiler/testData/codegen/box/coroutines/lambdaParameters.kt +++ b/compiler/testData/codegen/box/coroutines/lambdaParameters.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt b/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt index e9642558f23..712e194b317 100644 --- a/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt +++ b/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt @@ -5,6 +5,7 @@ class Controller { suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x -> result += v x.resume(Unit) + Suspend } operator fun handleResult(u: Unit, v: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/lastStatementInc.kt b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt index d6d3d9a4950..e14954ec7dd 100644 --- a/compiler/testData/codegen/box/coroutines/lastStatementInc.kt +++ b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt @@ -3,6 +3,7 @@ class Controller { var wasHandleResultCalled = false suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } operator fun handleResult(x: Unit, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt index 73b2f5109cd..9309a6f01b8 100644 --- a/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt +++ b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt @@ -3,6 +3,7 @@ class Controller { var wasHandleResultCalled = false suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } operator fun handleResult(x: Unit, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt b/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt index a0cc925dffa..206dffa019d 100644 --- a/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt +++ b/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt @@ -5,6 +5,7 @@ class Controller { suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x -> this.v = v x.resume(Unit) + Suspend } operator fun handleResult(u: Unit, v: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt b/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt index b4c279b733c..dca0deb25bb 100644 --- a/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt +++ b/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt @@ -3,6 +3,7 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/multiModule/simple.kt b/compiler/testData/codegen/box/coroutines/multiModule/simple.kt index d681b673e49..a29efe43d15 100644 --- a/compiler/testData/codegen/box/coroutines/multiModule/simple.kt +++ b/compiler/testData/codegen/box/coroutines/multiModule/simple.kt @@ -6,6 +6,7 @@ package lib class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt b/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt index de82e0a0356..fdf58ffee82 100644 --- a/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt +++ b/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt @@ -7,6 +7,7 @@ package lib class Controller { suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume(this) + Suspend } inline suspend fun String.inlineSuspendHere(): String = suspendHere() diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt index 9f816bed3c1..5801b4213ee 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt @@ -4,7 +4,7 @@ class Controller { var result = "fail" suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x - Unit + Suspend } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt index fcfe8be3204..6b058132ae3 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt @@ -4,7 +4,7 @@ class Controller { var result = "fail" suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x - Unit + Suspend } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt index 5830d52f96f..39e8f60ead6 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt @@ -4,7 +4,7 @@ class Controller { var result = "fail" suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x - Unit + Suspend } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt index b5dd5379be0..d4e98efbb69 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt @@ -4,7 +4,7 @@ class Controller { var result = "fail" suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x - Unit + Suspend } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt b/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt index 7ac39b1f75b..58b0da2f958 100644 --- a/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt +++ b/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt @@ -9,12 +9,16 @@ class Controller { postponedActions.add { x.resume(v) } + + Suspend } suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } + + Suspend } operator fun handleResult(x: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt index b8b4af26398..0038715d865 100644 --- a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt @@ -3,6 +3,7 @@ class Controller { var cResult = 0 suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x -> x.resume(v * 2) + Suspend } operator fun handleResult(x: Int, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt index fd3565240ea..55f96a6cc92 100644 --- a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt +++ b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt @@ -5,6 +5,7 @@ class Controller { var cResult = 0 suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x -> x.resume(v * 2) + Suspend } operator fun handleResult(x: Int, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/returnByLabel.kt b/compiler/testData/codegen/box/coroutines/returnByLabel.kt index ee44c551568..21f3bc3bfca 100644 --- a/compiler/testData/codegen/box/coroutines/returnByLabel.kt +++ b/compiler/testData/codegen/box/coroutines/returnByLabel.kt @@ -3,6 +3,7 @@ class Controller { var res = 0 suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } operator fun handleResult(x: Int, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/simple.kt b/compiler/testData/codegen/box/coroutines/simple.kt index 7de1c625045..5e51548c6d3 100644 --- a/compiler/testData/codegen/box/coroutines/simple.kt +++ b/compiler/testData/codegen/box/coroutines/simple.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/simpleException.kt b/compiler/testData/codegen/box/coroutines/simpleException.kt index 40107db3b6f..c1730ede0c0 100644 --- a/compiler/testData/codegen/box/coroutines/simpleException.kt +++ b/compiler/testData/codegen/box/coroutines/simpleException.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resumeWithException(RuntimeException("OK")) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt index 699f03f1dfa..ceaf128950d 100644 --- a/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt @@ -3,6 +3,7 @@ class Controller { var res = 0 suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } operator fun handleResult(x: Int, y: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt b/compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt new file mode 100644 index 00000000000..0c9e2b02253 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt @@ -0,0 +1,19 @@ +class Controller { + suspend fun suspendHere(): String = throw RuntimeException("OK") + + // INTERCEPT_RESUME_PLACEHOLDER +} + +fun builder(coroutine c: Controller.() -> Continuation) { + c(Controller()).resume(Unit) +} + +fun box(): String { + var result = "" + + builder { + result = try { suspendHere() } catch (e: RuntimeException) { e.message!! } + } + + return result +} diff --git a/compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt b/compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt new file mode 100644 index 00000000000..498030d3d6e --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt @@ -0,0 +1,36 @@ +// WITH_RUNTIME +// WITH_REFLECT +// CHECK_NOT_CALLED: suspendInline_die06n$ +// CHECK_NOT_CALLED: suspendInline_nesahw$ +// CHECK_NOT_CALLED: suspendInline_grpnnl$ +class Controller { + suspend inline fun suspendInline(v: String): String = v + + suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b()) + + suspend inline fun suspendInline(): String = suspendInline({ T::class.simpleName!! }) + + // INTERCEPT_RESUME_PLACEHOLDER +} + +fun builder(coroutine c: Controller.() -> Continuation) { + c(Controller()).resume(Unit) +} + +class OK + +fun box(): String { + var result = "" + + builder { + result = suspendInline("56") + if (result != "56") throw RuntimeException("fail 1") + + result = suspendInline { "57" } + if (result != "57") throw RuntimeException("fail 2") + + result = suspendInline() + } + + return result +} diff --git a/compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt b/compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt new file mode 100644 index 00000000000..611c333d5ee --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt @@ -0,0 +1,19 @@ +class Controller { + suspend fun suspendHere() = "OK" + + // INTERCEPT_RESUME_PLACEHOLDER +} + +fun builder(coroutine c: Controller.() -> Continuation) { + c(Controller()).resume(Unit) +} + +fun box(): String { + var result = "" + + builder { + result = suspendHere() + } + + return result +} diff --git a/compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt b/compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt new file mode 100644 index 00000000000..223f33bf951 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt @@ -0,0 +1,47 @@ +// IGNORE_BACKEND: JS +class Controller { + suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x -> + 1 + } + suspend fun suspendThere(): String = suspendWithCurrentContinuation { x -> + "?" + } + + // INTERCEPT_RESUME_PLACEHOLDER +} + +fun builder(coroutine c: Controller.() -> Continuation) { + c(Controller()).resume(Unit) +} + +fun box(): String { + var result = "" + + builder { + result += "-" + for (i in 0..10000) { + if (i % 2 == 0) { + result += suspendHere().toString() + } + else if (i == 3) { + result += suspendThere() + } + } + result += "+" + } + + var mustBe = "-" + for (i in 0..10000) { + if (i % 2 == 0) { + mustBe += "1" + } + else if (i == 3) { + mustBe += "?" + } + } + mustBe += "+" + + if (result != mustBe) return "fail: $result/$mustBe" + + return "OK" +} diff --git a/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt b/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt index a32e1651929..b864c70f995 100644 --- a/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt +++ b/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt @@ -3,6 +3,7 @@ var globalResult = "" class Controller { suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) + Suspend } operator fun handleResult(x: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/suspendDelegation.kt b/compiler/testData/codegen/box/coroutines/suspendDelegation.kt index a1e11ba2b90..c35def708ce 100644 --- a/compiler/testData/codegen/box/coroutines/suspendDelegation.kt +++ b/compiler/testData/codegen/box/coroutines/suspendDelegation.kt @@ -4,6 +4,7 @@ class Controller { suspend fun suspendThere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/suspendExtension.kt b/compiler/testData/codegen/box/coroutines/suspendExtension.kt index 3fb6354d155..3f534a43fa4 100644 --- a/compiler/testData/codegen/box/coroutines/suspendExtension.kt +++ b/compiler/testData/codegen/box/coroutines/suspendExtension.kt @@ -3,6 +3,7 @@ class Controller { suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume(this) + Suspend } inline suspend fun String.inlineSuspendHere(): String = suspendHere() diff --git a/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt b/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt index 9d05e4fe48f..9ca15aa5721 100644 --- a/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x -> x.resume(v * 2) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/suspendInCycle.kt b/compiler/testData/codegen/box/coroutines/suspendInCycle.kt index 47707901368..d5762c41dd4 100644 --- a/compiler/testData/codegen/box/coroutines/suspendInCycle.kt +++ b/compiler/testData/codegen/box/coroutines/suspendInCycle.kt @@ -3,9 +3,11 @@ class Controller { var i = 0 suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x -> x.resume(i++) + Suspend } suspend fun suspendThere(): String = suspendWithCurrentContinuation { x -> x.resume("?") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt index 59453796f2d..7afc9e094a4 100644 --- a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt +++ b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt @@ -2,14 +2,17 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("K") + Suspend } suspend fun suspendWithArgument(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) + Suspend } suspend fun suspendWithDouble(v: Double): Double = suspendWithCurrentContinuation { x -> x.resume(v) + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt index 1c318eb5949..6c7e2d74eea 100644 --- a/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt @@ -9,12 +9,16 @@ class Controller { postponedActions.add { x.resume(v) } + + Suspend } suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } + + Suspend } operator fun handleResult(x: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt index 53e8aadb5df..aa2ebfa585e 100644 --- a/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt @@ -9,12 +9,16 @@ class Controller { postponedActions.add { x.resume(v) } + + Suspend } suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } + + Suspend } operator fun handleResult(x: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt index 6941d23f1b0..f0039408f92 100644 --- a/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt @@ -2,6 +2,8 @@ class Controller { suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) + + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt index d5488f53782..0b6327eef53 100644 --- a/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt @@ -9,12 +9,16 @@ class Controller { postponedActions.add { x.resume(v) } + + Suspend } suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } + + Suspend } operator fun handleResult(x: String, c: Continuation) { diff --git a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt index 12602933f1a..be04b47af1f 100644 --- a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt +++ b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt index 0636494d430..a028a050070 100644 --- a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt +++ b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt @@ -2,6 +2,7 @@ class Controller { suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } // INTERCEPT_RESUME_PLACEHOLDER diff --git a/compiler/testData/codegen/bytecodeListing/coroutineFields.txt b/compiler/testData/codegen/bytecodeListing/coroutineFields.txt index 959727121c8..e2f397fc242 100644 --- a/compiler/testData/codegen/bytecodeListing/coroutineFields.txt +++ b/compiler/testData/codegen/bytecodeListing/coroutineFields.txt @@ -1,7 +1,7 @@ @kotlin.Metadata public final class Controller { public method (): void - public final method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object } @kotlin.Metadata diff --git a/compiler/testData/codegen/bytecodeText/constCoroutine.kt b/compiler/testData/codegen/bytecodeText/constCoroutine.kt index e2324a99a4f..2e0712f8cac 100644 --- a/compiler/testData/codegen/bytecodeText/constCoroutine.kt +++ b/compiler/testData/codegen/bytecodeText/constCoroutine.kt @@ -19,4 +19,5 @@ fun box(): String { } // 1 GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit; -// 1 GETSTATIC +// 1 GETSTATIC kotlin/coroutines/Suspend.INSTANCE +// 2 GETSTATIC diff --git a/compiler/testData/codegen/java8/box/async.kt b/compiler/testData/codegen/java8/box/async.kt index 2d042e9fa80..506398dea51 100644 --- a/compiler/testData/codegen/java8/box/async.kt +++ b/compiler/testData/codegen/java8/box/async.kt @@ -60,6 +60,8 @@ class FutureController { else machine.resumeWithException(throwable) } + + Suspend } operator fun handleResult(value: T, c: Continuation) { diff --git a/compiler/testData/codegen/java8/box/asyncException.kt b/compiler/testData/codegen/java8/box/asyncException.kt index 2de61e85c48..02aeb7af5e0 100644 --- a/compiler/testData/codegen/java8/box/asyncException.kt +++ b/compiler/testData/codegen/java8/box/asyncException.kt @@ -56,6 +56,8 @@ class FutureController { else machine.resumeWithException(throwable) } + + Suspend } operator fun handleResult(value: T, c: Continuation) { diff --git a/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt b/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt index 74101e8817c..4f6614feeb5 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt @@ -3,6 +3,7 @@ package a class Controller { suspend fun suspendHere() = suspendWithCurrentContinuation { x -> x.resume("OK") + Suspend } } diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index bb3a54eb83c..465464b2b2f 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -4945,6 +4945,39 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class StackUnwinding extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInStackUnwinding() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("exception.kt") + public void testException() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt"); + doTest(fileName); + } + + @TestMetadata("inlineSuspendFunction.kt") + public void testInlineSuspendFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt"); + doTest(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt"); + doTest(fileName); + } + + @TestMetadata("suspendInCycle.kt") + public void testSuspendInCycle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/dataClasses") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/AdditionalCoroutineBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/AdditionalCoroutineBlackBoxCodegenTestGenerated.java index 56242791130..58c2108e44c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/AdditionalCoroutineBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/AdditionalCoroutineBlackBoxCodegenTestGenerated.java @@ -423,4 +423,37 @@ public class AdditionalCoroutineBlackBoxCodegenTestGenerated extends AbstractAdd doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class StackUnwinding extends AbstractAdditionalCoroutineBlackBoxCodegenTest { + public void testAllFilesPresentInStackUnwinding() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("exception.kt") + public void testException() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt"); + doTest(fileName); + } + + @TestMetadata("inlineSuspendFunction.kt") + public void testInlineSuspendFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt"); + doTest(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt"); + doTest(fileName); + } + + @TestMetadata("suspendInCycle.kt") + public void testSuspendInCycle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt"); + doTest(fileName); + } + } } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 697c797c140..b1005a92108 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -4945,6 +4945,39 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class StackUnwinding extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInStackUnwinding() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("exception.kt") + public void testException() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt"); + doTest(fileName); + } + + @TestMetadata("inlineSuspendFunction.kt") + public void testInlineSuspendFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt"); + doTest(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt"); + doTest(fileName); + } + + @TestMetadata("suspendInCycle.kt") + public void testSuspendInCycle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/dataClasses") 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 084dbe8e94e..6d47ca261e2 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 @@ -6152,6 +6152,45 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class StackUnwinding extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInStackUnwinding() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("exception.kt") + public void testException() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt"); + doTest(fileName); + } + + @TestMetadata("inlineSuspendFunction.kt") + public void testInlineSuspendFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt"); + doTest(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt"); + doTest(fileName); + } + + @TestMetadata("suspendInCycle.kt") + public void testSuspendInCycle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt"); + try { + doTest(fileName); + } + catch (Throwable ignore) { + return; + } + throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + } + } } @TestMetadata("compiler/testData/codegen/box/dataClasses")