diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 88957894c26..bd815051aa4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -3590,30 +3590,41 @@ public class ExpressionCodegen extends KtVisitor impleme return StackValue.cmp(expression.getOperationToken(), type, leftValue, rightValue); } - private StackValue generateAssignmentExpression(KtBinaryExpression expression) { - StackValue stackValue = gen(expression.getLeft()); - KtExpression right = expression.getRight(); - assert right != null : expression.getText(); - stackValue.store(gen(right), v); - return StackValue.none(); + private StackValue generateAssignmentExpression(final KtBinaryExpression expression) { + return StackValue.operation(Type.VOID_TYPE, new Function1() { + @Override + public Unit invoke(InstructionAdapter adapter) { + StackValue stackValue = gen(expression.getLeft()); + KtExpression right = expression.getRight(); + assert right != null : expression.getText(); + stackValue.store(gen(right), v); + + return Unit.INSTANCE; + } + }); } - private StackValue generateAugmentedAssignment(KtBinaryExpression expression) { - ResolvedCall resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); - FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall); - Callable callable = resolveToCallable(descriptor, false, resolvedCall); - KtExpression lhs = expression.getLeft(); - Type lhsType = expressionType(lhs); + private StackValue generateAugmentedAssignment(final KtBinaryExpression expression) { + return StackValue.operation(Type.VOID_TYPE, new Function1() { + @Override + public Unit invoke(InstructionAdapter adapter) { + ResolvedCall resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); + FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall); + Callable callable = resolveToCallable(descriptor, false, resolvedCall); + KtExpression lhs = expression.getLeft(); + Type lhsType = expressionType(lhs); - boolean keepReturnValue = Boolean.TRUE.equals(bindingContext.get(VARIABLE_REASSIGNMENT, expression)) - || !KotlinBuiltIns.isUnit(descriptor.getReturnType()); + boolean keepReturnValue = Boolean.TRUE.equals(bindingContext.get(VARIABLE_REASSIGNMENT, expression)) + || !KotlinBuiltIns.isUnit(descriptor.getReturnType()); - callAugAssignMethod(expression, resolvedCall, callable, lhsType, keepReturnValue); + putCallAugAssignMethod(expression, resolvedCall, callable, lhsType, keepReturnValue); - return StackValue.none(); + return Unit.INSTANCE; + } + }); } - private void callAugAssignMethod( + private void putCallAugAssignMethod( @NotNull KtBinaryExpression expression, @NotNull ResolvedCall resolvedCall, @NotNull Callable callable, diff --git a/compiler/testData/codegen/box/coroutines/lastStatementInc.kt b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt new file mode 100644 index 00000000000..be98bbc480d --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt @@ -0,0 +1,43 @@ +class Controller { + var wasHandleResultCalled = false + suspend fun suspendHere(x: Continuation) { + x.resume("OK") + } + + operator fun handleResult(x: Unit, y: Continuation) { + wasHandleResultCalled = true + } +} + +fun builder(coroutine c: Controller.() -> Continuation) { + val controller = Controller() + c(controller).resume(Unit) + + if (!controller.wasHandleResultCalled) throw java.lang.RuntimeException("fail 1") +} + +fun box(): String { + var result = 0 + + builder { + result++ + + if (suspendHere() != "OK") throw java.lang.RuntimeException("fail 2") + + result-- + } + + if (result != 0) return "fail 3" + + builder { + --result + + if (suspendHere() != "OK") throw java.lang.RuntimeException("fail 4") + + ++result + } + + if (result != 0) return "fail 5" + + return "OK" +} diff --git a/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt new file mode 100644 index 00000000000..75e0f914a12 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt @@ -0,0 +1,45 @@ +class Controller { + var wasHandleResultCalled = false + suspend fun suspendHere(x: Continuation) { + x.resume("OK") + } + + operator fun handleResult(x: Unit, y: Continuation) { + wasHandleResultCalled = true + } +} + +fun builder(coroutine c: Controller.() -> Continuation) { + val controller = Controller() + c(controller).resume(Unit) + + if (!controller.wasHandleResultCalled) throw java.lang.RuntimeException("fail 1") +} + +var varWithCustomSetter: String = "" + set(value) { + if (field != "") throw java.lang.RuntimeException("fail 2") + field = value + } + +fun box(): String { + var result = "" + + builder { + result += "O" + + if (suspendHere() != "OK") throw java.lang.RuntimeException("fail 3") + + result += "K" + } + + if (result != "OK") return "fail 4" + + builder { + if (suspendHere() != "OK") throw java.lang.RuntimeException("fail 5") + + varWithCustomSetter = "OK" + } + + return varWithCustomSetter +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b7ac3f19377..6fb20c3bb1a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -4285,6 +4285,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("lastStatementInc.kt") + public void testLastStatementInc() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lastStatementInc.kt"); + doTest(fileName); + } + + @TestMetadata("lastStementAssignment.kt") + public void testLastStementAssignment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lastStementAssignment.kt"); + doTest(fileName); + } + @TestMetadata("lastUnitExpression.kt") public void testLastUnitExpression() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/lastUnitExpression.kt");