Fix coroutine generation in case of empty lambda
'handleResult' should be called in such case too
This commit is contained in:
@@ -570,7 +570,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
statements.addAll(doWhileStatements);
|
||||
statements.add(condition);
|
||||
|
||||
conditionValue = generateBlock(statements, false, continueLabel, null);
|
||||
conditionValue = generateBlock((KtBlockExpression) body, statements, false, continueLabel, null);
|
||||
}
|
||||
else {
|
||||
if (body != null) {
|
||||
@@ -1678,9 +1678,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
/* package */ StackValue generateBlock(@NotNull KtBlockExpression expression, boolean isStatement) {
|
||||
if (expression.getParent() instanceof KtNamedFunction) {
|
||||
// For functions end of block should be end of function label
|
||||
return generateBlock(expression.getStatements(), isStatement, null, context.getMethodEndLabel());
|
||||
return generateBlock(expression, expression.getStatements(), isStatement, null, context.getMethodEndLabel());
|
||||
}
|
||||
return generateBlock(expression.getStatements(), isStatement, null, null);
|
||||
return generateBlock(expression, expression.getStatements(), isStatement, null, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1695,16 +1695,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private StackValue generateBlock(
|
||||
List<KtExpression> statements,
|
||||
@NotNull KtBlockExpression block,
|
||||
@NotNull List<KtExpression> statements,
|
||||
boolean isStatement,
|
||||
Label labelBeforeLastExpression,
|
||||
@Nullable Label labelBeforeLastExpression,
|
||||
@Nullable final Label labelBlockEnd
|
||||
) {
|
||||
final Label blockEnd = labelBlockEnd != null ? labelBlockEnd : new Label();
|
||||
|
||||
final List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList();
|
||||
|
||||
StackValue answer = StackValue.none();
|
||||
@Nullable
|
||||
StackValue answer = null;
|
||||
|
||||
for (Iterator<KtExpression> iterator = statements.iterator(); iterator.hasNext(); ) {
|
||||
KtExpression possiblyLabeledStatement = iterator.next();
|
||||
@@ -1731,9 +1733,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
if (!iterator.hasNext()) {
|
||||
answer = result;
|
||||
StackValue handleResultValue = !(possiblyLabeledStatement instanceof KtReturnExpression)
|
||||
? genControllerHandleResultCallIfNeeded(possiblyLabeledStatement, possiblyLabeledStatement)
|
||||
: null;
|
||||
StackValue handleResultValue = genControllerHandleResultForLastStatementInCoroutine(block, possiblyLabeledStatement);
|
||||
if (handleResultValue != null) {
|
||||
answer = handleResultValue;
|
||||
}
|
||||
@@ -1745,6 +1745,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
addLeaveTaskToRemoveDescriptorFromFrameMap(statement, blockEnd, leaveTasks);
|
||||
}
|
||||
|
||||
if (answer == null) {
|
||||
answer = genControllerHandleResultForLastStatementInCoroutine(block, null);
|
||||
if (answer == null) {
|
||||
answer = StackValue.none();
|
||||
}
|
||||
}
|
||||
|
||||
return new StackValueWithLeaveTask(answer, new Function1<StackValue, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(StackValue value) {
|
||||
@@ -1759,6 +1766,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StackValue genControllerHandleResultForLastStatementInCoroutine(
|
||||
@NotNull KtBlockExpression block,
|
||||
@Nullable KtExpression lastStatement
|
||||
) {
|
||||
if (!(block.getParent() instanceof KtFunctionLiteral)) return null;
|
||||
KtFunctionLiteral functionLiteral = (KtFunctionLiteral) block.getParent();
|
||||
|
||||
return genControllerHandleResultCallIfNeeded(functionLiteral, lastStatement);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private StackValue genControllerHandleResultCallIfNeeded(@NotNull KtExpression callOwner, @Nullable KtExpression valueToReturn) {
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(RETURN_HANDLE_RESULT_RESOLVED_CALL, callOwner);
|
||||
|
||||
@@ -114,12 +114,12 @@ class CallCompleter(
|
||||
|
||||
function.controllerTypeIfCoroutine ?: return@forEach
|
||||
|
||||
val lastBlockStatement = it.functionLiteral.bodyExpression?.statements?.lastOrNull() ?: return@forEach
|
||||
val lastBlockStatement = it.functionLiteral.bodyExpression?.statements?.lastOrNull()
|
||||
|
||||
// Already resolved
|
||||
if (lastBlockStatement is KtReturnExpression) return@forEach
|
||||
|
||||
fakeCallResolver.resolveCoroutineHandleResultCallIfNeeded(lastBlockStatement, lastBlockStatement, function, context)
|
||||
fakeCallResolver.resolveCoroutineHandleResultCallIfNeeded(it.functionLiteral, lastBlockStatement, function, context)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
class Controller {
|
||||
var ok = false
|
||||
|
||||
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
|
||||
ok = true
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(coroutine c: Controller.() -> Continuation<Unit>): String {
|
||||
val controller = Controller()
|
||||
c(controller).resume(Unit)
|
||||
if (!controller.ok) throw java.lang.RuntimeException("Was not called")
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun unitFun() {}
|
||||
|
||||
fun box(): String {
|
||||
return builder {}
|
||||
}
|
||||
@@ -4153,6 +4153,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("handleResultCallEmptyBody.kt")
|
||||
public void testHandleResultCallEmptyBody() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/handleResultCallEmptyBody.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("illegalState.kt")
|
||||
public void testIllegalState() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/illegalState.kt");
|
||||
|
||||
Reference in New Issue
Block a user