Refine returns codegen for suspend functions
This change should make the logic a bit more simple. For all suspend functions/coroutines treat them in expression codegen like they return boxed version of the original type. Everything works fine then, except Unit type functions: their bodies must be generated just like they're VOID and then load Unit on stack manually.
This commit is contained in:
@@ -127,7 +127,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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<StackValue, StackValue> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
@@ -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<Unit> {
|
||||
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
|
||||
}
|
||||
@@ -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<Unit> {
|
||||
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
|
||||
}
|
||||
+34
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Vendored
+19
@@ -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 <init>(): 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
|
||||
}
|
||||
+19
@@ -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 <init>(): 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
|
||||
}
|
||||
Vendored
+22
@@ -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 <init>(): 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
|
||||
}
|
||||
+22
@@ -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 <init>(): 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
|
||||
}
|
||||
+33
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
+33
@@ -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")
|
||||
|
||||
+39
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user