Fix assignment codegen for suspend operators plus and plusAssign
KT-16079: Fixed
This commit is contained in:
@@ -2171,15 +2171,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
resolvedCall, state.getProject(), state.getBindingContext()
|
||||
);
|
||||
if (callWithRealDescriptor != null) {
|
||||
StackValue coroutineInstanceValueForSuspensionPoint = getCoroutineInstanceValueForSuspensionPoint(resolvedCall);
|
||||
StackValue coroutineInstanceValue =
|
||||
coroutineInstanceValueForSuspensionPoint != null
|
||||
? coroutineInstanceValueForSuspensionPoint
|
||||
: getContinuationParameterFromEnclosingSuspendFunction(resolvedCall);
|
||||
tempVariables.put(callWithRealDescriptor.getFakeContinuationExpression(), coroutineInstanceValue);
|
||||
|
||||
prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression());
|
||||
return invokeFunction(callWithRealDescriptor.getResolvedCall(), receiver);
|
||||
}
|
||||
|
||||
FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall);
|
||||
ClassDescriptor superCallTarget = getSuperCallTarget(call);
|
||||
|
||||
@@ -2199,6 +2194,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||
}
|
||||
|
||||
private void prepareCoroutineArgumentForSuspendCall(
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@NotNull KtExpression continuationExpression
|
||||
) {
|
||||
StackValue coroutineInstanceValueForSuspensionPoint = getCoroutineInstanceValueForSuspensionPoint(resolvedCall);
|
||||
StackValue coroutineInstanceValue =
|
||||
coroutineInstanceValueForSuspensionPoint != null
|
||||
? coroutineInstanceValueForSuspensionPoint
|
||||
: getContinuationParameterFromEnclosingSuspendFunction(resolvedCall);
|
||||
tempVariables.put(continuationExpression, coroutineInstanceValue);
|
||||
}
|
||||
|
||||
private StackValue getContinuationParameterFromEnclosingSuspendFunction(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
FunctionDescriptor enclosingSuspendFunction =
|
||||
bindingContext.get(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall());
|
||||
@@ -3405,6 +3412,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private StackValue generateAugmentedAssignment(KtBinaryExpression expression) {
|
||||
return StackValue.operation(Type.VOID_TYPE, adapter -> {
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext);
|
||||
|
||||
ResolvedCallWithRealDescriptor callWithRealDescriptor =
|
||||
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(
|
||||
resolvedCall, state.getProject(), state.getBindingContext()
|
||||
);
|
||||
if (callWithRealDescriptor != null) {
|
||||
prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression());
|
||||
resolvedCall = callWithRealDescriptor.getResolvedCall();
|
||||
}
|
||||
|
||||
FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall);
|
||||
Callable callable = resolveToCallable(descriptor, false, resolvedCall);
|
||||
KtExpression lhs = expression.getLeft();
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
suspend fun suspendThere(v: A): A = suspendCoroutineOrReturn { x ->
|
||||
x.resume(v)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
class A(var value: String) {
|
||||
operator suspend fun plus(other: A) = suspendThere(A(value + other.value))
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun usePlusAssign(): A {
|
||||
var a = A("O")
|
||||
a += A("K")
|
||||
return a
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var a = A("")
|
||||
builder { a = usePlusAssign() }
|
||||
return a.value
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
suspend fun suspendThere(v: A): A = suspendCoroutineOrReturn { x ->
|
||||
x.resume(v)
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
class A(var value: String) {
|
||||
operator suspend fun plusAssign(other: A) {
|
||||
value = suspendThere(A(value + other.value)).value
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun usePlusAssign(): A {
|
||||
var a = A("O")
|
||||
a += A("K")
|
||||
return a
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var a = A("")
|
||||
builder { a = usePlusAssign() }
|
||||
return a.value
|
||||
}
|
||||
-2
@@ -1,9 +1,7 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
|
||||
// TODO: looks like this is a bug in JVM backend
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
+18
-12
@@ -5938,6 +5938,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlus.kt")
|
||||
public void testSuspendOperatorPlus() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlus.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusAssign.kt")
|
||||
public void testSuspendOperatorPlusAssign() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusCallFromLambda.kt")
|
||||
public void testSuspendOperatorPlusCallFromLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusCallFromLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tailrec.kt")
|
||||
public void testTailrec() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/tailrec.kt");
|
||||
@@ -6145,18 +6163,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("augmentedAssignment.kt")
|
||||
public void testAugmentedAssignment() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/augmentedAssignment.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("dispatchResume.kt")
|
||||
public void testDispatchResume() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/dispatchResume.kt");
|
||||
|
||||
@@ -5938,6 +5938,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlus.kt")
|
||||
public void testSuspendOperatorPlus() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlus.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusAssign.kt")
|
||||
public void testSuspendOperatorPlusAssign() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusCallFromLambda.kt")
|
||||
public void testSuspendOperatorPlusCallFromLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusCallFromLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tailrec.kt")
|
||||
public void testTailrec() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/tailrec.kt");
|
||||
@@ -6145,18 +6163,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("augmentedAssignment.kt")
|
||||
public void testAugmentedAssignment() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/augmentedAssignment.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("dispatchResume.kt")
|
||||
public void testDispatchResume() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/dispatchResume.kt");
|
||||
|
||||
@@ -5938,6 +5938,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlus.kt")
|
||||
public void testSuspendOperatorPlus() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlus.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusAssign.kt")
|
||||
public void testSuspendOperatorPlusAssign() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusCallFromLambda.kt")
|
||||
public void testSuspendOperatorPlusCallFromLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusCallFromLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tailrec.kt")
|
||||
public void testTailrec() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/tailrec.kt");
|
||||
@@ -6141,18 +6159,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SuspendFunctionAsCoroutine extends AbstractLightAnalysisModeTest {
|
||||
@TestMetadata("augmentedAssignment.kt")
|
||||
public void ignoreAugmentedAssignment() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/augmentedAssignment.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSuspendFunctionAsCoroutine() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
+18
-6
@@ -6514,6 +6514,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlus.kt")
|
||||
public void testSuspendOperatorPlus() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlus.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusAssign.kt")
|
||||
public void testSuspendOperatorPlusAssign() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusAssign.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("suspendOperatorPlusCallFromLambda.kt")
|
||||
public void testSuspendOperatorPlusCallFromLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/suspendOperatorPlusCallFromLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tailrec.kt")
|
||||
public void testTailrec() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/featureIntersection/tailrec.kt");
|
||||
@@ -6703,12 +6721,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("augmentedAssignment.kt")
|
||||
public void testAugmentedAssignment() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/augmentedAssignment.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dispatchResume.kt")
|
||||
public void testDispatchResume() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/dispatchResume.kt");
|
||||
|
||||
Reference in New Issue
Block a user