diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index e0e1924c883..ce1a51f0b4f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -127,7 +127,6 @@ public class ExpressionCodegen extends KtVisitor impleme public final FrameMap myFrameMap; public final MethodContext context; private final Type returnType; - private final Type boxedReturnTypeForCoroutine; private final CodegenStatementVisitor statementVisitor = new CodegenStatementVisitor(this); private final MemberCodegen parentCodegen; @@ -161,14 +160,12 @@ public class ExpressionCodegen extends KtVisitor impleme this.myFrameMap = frameMap; this.context = context; - FunctionDescriptor descriptorForCoroutine = getOriginalLambdaDescriptorForCoroutine(context); - if (descriptorForCoroutine != null && descriptorForCoroutine.getReturnType() != null) { - this.returnType = typeMapper.mapReturnType(descriptorForCoroutine); - this.boxedReturnTypeForCoroutine = getBoxedReturnTypeForCoroutine(descriptorForCoroutine); + FunctionDescriptor originalSuspendDescriptor = getOriginalSuspendDescriptor(context); + if (originalSuspendDescriptor != null && originalSuspendDescriptor.getReturnType() != null) { + this.returnType = getBoxedReturnTypeForSuspend(originalSuspendDescriptor); } else { this.returnType = returnType; - this.boxedReturnTypeForCoroutine = null; } this.parentCodegen = parentCodegen; @@ -176,18 +173,31 @@ public class ExpressionCodegen extends KtVisitor impleme } @NotNull - private Type getBoxedReturnTypeForCoroutine(FunctionDescriptor descriptorForCoroutine) { - assert descriptorForCoroutine.getReturnType() != null : "Uninitialized coroutine return type"; - return AsmUtil.boxType(typeMapper.mapType(descriptorForCoroutine.getReturnType())); + private Type getBoxedReturnTypeForSuspend(FunctionDescriptor descriptorForSuspend) { + assert descriptorForSuspend.getReturnType() != null : "Uninitialized suspend return type"; + return AsmUtil.boxType(typeMapper.mapType(descriptorForSuspend.getReturnType())); } @Nullable - private static FunctionDescriptor getOriginalLambdaDescriptorForCoroutine(MethodContext context) { + private static FunctionDescriptor getOriginalSuspendDescriptor(MethodContext context) { + FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context); + if (originalCoroutineDescriptor != null) return originalCoroutineDescriptor; + + if (context.getFunctionDescriptor().isSuspend()) { + return (FunctionDescriptor) CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(context.getFunctionDescriptor()); + } + + return null; + } + + @Nullable + private static FunctionDescriptor getOriginalCoroutineDescriptor(MethodContext context) { if ((context.getParentContext() instanceof ClosureContext) && (context.getParentContext().closure != null) && context.getParentContext().closure.isCoroutine()) { return ((ClosureContext) context.getParentContext()).getCoroutineDescriptor(); } + return null; } @@ -351,7 +361,7 @@ public class ExpressionCodegen extends KtVisitor impleme putStackValue(expr, type, value); } - private void putStackValue(KtElement expr, Type type, StackValue value) { + private void putStackValue(@Nullable KtElement expr, @NotNull Type type, @NotNull StackValue value) { // for repl store the result of the last line into special field if (value.type != Type.VOID_TYPE && state.getReplSpecific().getShouldGenerateScriptResultValue()) { ScriptContext context = getScriptContext(); @@ -1775,7 +1785,7 @@ public class ExpressionCodegen extends KtVisitor impleme @NotNull private static CallableDescriptor unwrapOriginalLambdaDescriptorForCoroutine(@NotNull MethodContext context) { - FunctionDescriptor coroutine = getOriginalLambdaDescriptorForCoroutine(context); + FunctionDescriptor coroutine = getOriginalSuspendDescriptor(context); if (coroutine != null) return coroutine; return context.getFunctionDescriptor(); } @@ -2159,26 +2169,19 @@ public class ExpressionCodegen extends KtVisitor impleme } Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : ExpressionCodegen.this.returnType; - StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : null; + StackValue valueToReturn = returnedExpression != null ? gen(returnedExpression) : StackValue.none(); - if (returnedExpression != null && valueToReturn != null) { - putStackValue(returnedExpression, returnType, valueToReturn); - } + putStackValue(returnedExpression, returnType, valueToReturn); Label afterReturnLabel = new Label(); generateFinallyBlocksIfNeeded(returnType, afterReturnLabel); if (isNonLocalReturn) { - if (nonLocalReturn.boxedCoroutineReturnType != null && !nonLocalReturn.boxedCoroutineReturnType.equals(returnType)) { - StackValue.coerce(nonLocalReturn.returnType, nonLocalReturn.boxedCoroutineReturnType, v); - returnType = nonLocalReturn.boxedCoroutineReturnType; - } - InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName); v.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); } else { - emitLocalReturnInsn(); + v.areturn(ExpressionCodegen.this.returnType); } v.mark(afterReturnLabel); @@ -2213,7 +2216,7 @@ public class ExpressionCodegen extends KtVisitor impleme FunctionDescriptor containingFunction = BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst(); //FIRST_FUN_LABEL to prevent clashing with existing labels - return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL, null); + return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL); } else { //local return null; @@ -2225,49 +2228,49 @@ public class ExpressionCodegen extends KtVisitor impleme DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element); assert element != null : "Expression should be not null " + expression.getText(); assert elementDescriptor != null : "Descriptor should be not null: " + element.getText(); - Type boxedCoroutineReturnType = - elementDescriptor instanceof AnonymousFunctionDescriptor - && ((AnonymousFunctionDescriptor) elementDescriptor).isCoroutine() - ? getBoxedReturnTypeForCoroutine((FunctionDescriptor) elementDescriptor) - : null; - return new NonLocalReturnInfo( - typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName(), - boxedCoroutineReturnType - ); + return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(elementDescriptor), expression.getLabelName()); } } return null; } + @NotNull + private Type getReturnTypeForNonLocalReturn(DeclarationDescriptor elementDescriptor) { + return (elementDescriptor instanceof AnonymousFunctionDescriptor + && ((AnonymousFunctionDescriptor) elementDescriptor).isCoroutine()) + || (elementDescriptor instanceof FunctionDescriptor && ((FunctionDescriptor) elementDescriptor).isSuspend()) + ? getBoxedReturnTypeForSuspend((FunctionDescriptor) elementDescriptor) + : typeMapper.mapReturnType((CallableDescriptor) elementDescriptor); + } + public void returnExpression(KtExpression expr) { boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction; - // If generating body for named block-bodied function, generate it as sequence of statements - gen(expr, isBlockedNamedFunction ? Type.VOID_TYPE : returnType); + FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context); + boolean isVoidCoroutineLambda = + originalCoroutineDescriptor != null && typeMapper.mapReturnType(originalCoroutineDescriptor).getSort() == Type.VOID; + + // If generating body for named block-bodied function or Unit-typed coroutine lambda, generate it as sequence of statements + Type typeForExpression = + isBlockedNamedFunction || isVoidCoroutineLambda + ? Type.VOID_TYPE + : returnType; + + gen(expr, typeForExpression); // If it does not end with return we should return something // because if we don't there can be VerifyError (specific cases with Nothing-typed expressions) if (!endsWithReturn(expr)) { markLineNumber(expr, true); - if (isLambdaVoidBody(expr, returnType)) { + if (isLambdaVoidBody(expr, typeForExpression)) { markLineNumber((KtFunctionLiteral) expr.getParent(), true); } - if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) { + if (typeForExpression.getSort() == Type.VOID) { StackValue.none().put(returnType, v); } - emitLocalReturnInsn(); - } - } - - private void emitLocalReturnInsn() { - if (boxedReturnTypeForCoroutine != null && !boxedReturnTypeForCoroutine.equals(returnType)) { - StackValue.coerce(returnType, boxedReturnTypeForCoroutine, v); - v.areturn(boxedReturnTypeForCoroutine); - } - else { v.areturn(returnType); } } @@ -2783,6 +2786,15 @@ public class ExpressionCodegen extends KtVisitor impleme return new OperationStackValue(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda()); } + if (bindingContext.get(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall()) != null) { + // Suspend function's calls inside another suspend function should behave like they leave values of correct type, + // while real methods return java/lang/Object. + // NB: They are always in return position at the moment. + // If we didn't do this, StackValue.coerce would add proper CHECKCAST that would've failed in case of callee function + // returning SUSPENDED marker, which is instance of java/lang/Object. + return new OperationStackValue(returnType, ((OperationStackValue) result).getLambda()); + } + return result; } @@ -4713,12 +4725,10 @@ The "returned" value of try expression with no finally is either the last expres private final Type returnType; private final String labelName; - private final Type boxedCoroutineReturnType; - private NonLocalReturnInfo(@NotNull Type type, @NotNull String name, @Nullable Type boxedCoroutineReturnType) { + private NonLocalReturnInfo(@NotNull Type type, @NotNull String name) { returnType = type; labelName = name; - this.boxedCoroutineReturnType = boxedCoroutineReturnType; } } diff --git a/compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt b/compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt new file mode 100644 index 00000000000..0f462b8a2fe --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt @@ -0,0 +1,46 @@ +// WITH_RUNTIME +// WITH_COROUTINES +import kotlin.coroutines.* + +suspend fun suspendHere(): String = CoroutineIntrinsics.suspendCoroutineOrReturn { x -> + x.resume("OK") + CoroutineIntrinsics.SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + var wasResumeCalled = false + c.startCoroutine(object : Continuation { + override fun resume(value: Unit) { + wasResumeCalled = true + } + + override fun resumeWithException(exception: Throwable) { + + } + }) + + if (!wasResumeCalled) throw RuntimeException("fail 1") +} + +fun box(): String { + var result = "" + + builder { + run { + if (result == "") return@builder + } + suspendHere() + throw RuntimeException("fail 2") + } + + result = "fail1" + + builder { + run { + if (result == "") return@builder + } + result = suspendHere() + } + + return result +} diff --git a/compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt b/compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt new file mode 100644 index 00000000000..b237e7cf158 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt @@ -0,0 +1,42 @@ +// WITH_RUNTIME +// WITH_COROUTINES +import kotlin.coroutines.* + +suspend fun suspendHere(): String = CoroutineIntrinsics.suspendCoroutineOrReturn { x -> + x.resume("OK") + CoroutineIntrinsics.SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + var wasResumeCalled = false + c.startCoroutine(object : Continuation { + override fun resume(value: Unit) { + wasResumeCalled = true + } + + override fun resumeWithException(exception: Throwable) { + + } + }) + + if (!wasResumeCalled) throw RuntimeException("fail 1") +} + +fun box(): String { + var result = "" + + builder { + if (result == "") return@builder + suspendHere() + throw RuntimeException("fail 2") + } + + result = "fail" + + builder { + if (result == "") return@builder + result = suspendHere() + } + + return result +} diff --git a/compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt b/compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt new file mode 100644 index 00000000000..f0d6919046e --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt @@ -0,0 +1,34 @@ +// WITH_RUNTIME +// WITH_COROUTINES +// IGNORE_BACKEND: JS +import kotlin.coroutines.* + +var result = "0" + + +suspend fun suspendHere(x: Int): Unit { + run { + if (x == 0) return + if (x == 1) return@suspendHere + } + + result = "OK" + return CoroutineIntrinsics.suspendCoroutineOrReturn { x -> + x.resume(Unit) + CoroutineIntrinsics.SUSPENDED + } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun box(): String { + builder { + if (suspendHere(0) != Unit) throw RuntimeException("fail 1") + if (suspendHere(1) != Unit) throw RuntimeException("fail 2") + if (suspendHere(2) != Unit) throw RuntimeException("fail 3") + } + + return result +} diff --git a/compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt b/compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt new file mode 100644 index 00000000000..589be86c2eb --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt @@ -0,0 +1,27 @@ +// WITH_RUNTIME +// WITH_COROUTINES +import kotlin.coroutines.* + +var result = "0" + +suspend fun suspendHere(x: Int): Unit { + if (x == 0) return + result = "OK" + return CoroutineIntrinsics.suspendCoroutineOrReturn { x -> + x.resume(Unit) + CoroutineIntrinsics.SUSPENDED + } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun box(): String { + builder { + suspendHere(0) + suspendHere(1) + } + + return result +} diff --git a/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineNonLocalReturn.txt b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineNonLocalReturn.txt new file mode 100644 index 00000000000..4e055e4a9b0 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineNonLocalReturn.txt @@ -0,0 +1,19 @@ +public final class CoroutineNonLocalReturnKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void + public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object +} + + +public final class CoroutineUtilKt { + public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation + public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation +} + + +public final class EmptyContinuation { + public final static field INSTANCE: EmptyContinuation + private method (): void + public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} diff --git a/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineReturn.txt b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineReturn.txt new file mode 100644 index 00000000000..eadf509b64e --- /dev/null +++ b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/coroutineReturn.txt @@ -0,0 +1,19 @@ +public final class CoroutineReturnKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void + public final static @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object +} + + +public final class CoroutineUtilKt { + public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation + public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation +} + + +public final class EmptyContinuation { + public final static field INSTANCE: EmptyContinuation + private method (): void + public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} diff --git a/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendNonLocalReturn.txt b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendNonLocalReturn.txt new file mode 100644 index 00000000000..3603b7480c9 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendNonLocalReturn.txt @@ -0,0 +1,22 @@ +public final class CoroutineUtilKt { + public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation + public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation +} + + +public final class EmptyContinuation { + public final static field INSTANCE: EmptyContinuation + private method (): void + public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} + + +public final class SuspendNonLocalReturnKt { + private static @org.jetbrains.annotations.NotNull field result: java.lang.String + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void + public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String + public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final static @org.jetbrains.annotations.Nullable method suspendHere(p0: int, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} diff --git a/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendReturn.txt b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendReturn.txt new file mode 100644 index 00000000000..2081d32289d --- /dev/null +++ b/compiler/testData/codegen/light-analysis/coroutines/unitTypeReturn/suspendReturn.txt @@ -0,0 +1,22 @@ +public final class CoroutineUtilKt { + public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation + public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.Continuation +} + + +public final class EmptyContinuation { + public final static field INSTANCE: EmptyContinuation + private method (): void + public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void + public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void +} + + +public final class SuspendReturnKt { + private static @org.jetbrains.annotations.NotNull field result: java.lang.String + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void + public final static @org.jetbrains.annotations.NotNull method getResult(): java.lang.String + public final static method setResult(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final static @org.jetbrains.annotations.Nullable method suspendHere(p0: int, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} 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 5adfc6724ad..bab59fa3ad9 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 @@ -4966,6 +4966,39 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UnitTypeReturn extends AbstractIrBlackBoxCodegenTest { + public void testAllFilesPresentInUnitTypeReturn() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/unitTypeReturn"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("coroutineNonLocalReturn.kt") + public void testCoroutineNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("coroutineReturn.kt") + public void testCoroutineReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt"); + doTest(fileName); + } + + @TestMetadata("suspendNonLocalReturn.kt") + public void testSuspendNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("suspendReturn.kt") + public void testSuspendReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/dataClasses") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index e9d327835f1..85748b762df 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -4966,6 +4966,39 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UnitTypeReturn extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInUnitTypeReturn() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/unitTypeReturn"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("coroutineNonLocalReturn.kt") + public void testCoroutineNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("coroutineReturn.kt") + public void testCoroutineReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt"); + doTest(fileName); + } + + @TestMetadata("suspendNonLocalReturn.kt") + public void testSuspendNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("suspendReturn.kt") + public void testSuspendReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/dataClasses") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java index a39d2307ac6..69a6e2c0aee 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java @@ -4966,6 +4966,39 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UnitTypeReturn extends AbstractLightAnalysisModeCodegenTest { + public void testAllFilesPresentInUnitTypeReturn() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/unitTypeReturn"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("coroutineNonLocalReturn.kt") + public void testCoroutineNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("coroutineReturn.kt") + public void testCoroutineReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt"); + doTest(fileName); + } + + @TestMetadata("suspendNonLocalReturn.kt") + public void testSuspendNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("suspendReturn.kt") + public void testSuspendReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.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 81ab72d3bb1..fddab863f19 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 @@ -5765,6 +5765,45 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UnitTypeReturn extends AbstractJsCodegenBoxTest { + public void testAllFilesPresentInUnitTypeReturn() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/unitTypeReturn"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("coroutineNonLocalReturn.kt") + public void testCoroutineNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("coroutineReturn.kt") + public void testCoroutineReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/coroutineReturn.kt"); + doTest(fileName); + } + + @TestMetadata("suspendNonLocalReturn.kt") + public void testSuspendNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendNonLocalReturn.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("suspendReturn.kt") + public void testSuspendReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/unitTypeReturn/suspendReturn.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/dataClasses")