JS: fix translation of augmented assignment when RHS changes value of LHS
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
// NO_INTERCEPT_RESUME_TESTS
|
||||
|
||||
// TODO: fix bug in JVM backend and remove this directive
|
||||
// TARGET_BACKEND: JS
|
||||
|
||||
class Controller {
|
||||
var result = ""
|
||||
|
||||
@@ -29,7 +26,7 @@ fun box(): String {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value != "A;[B][C]!") return "fail: suspend as if condition: $value"
|
||||
if (value != "A;B]C]!") return "fail: suspend as if condition: $value"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// WITH_RUNTIME
|
||||
import kotlin.test.*
|
||||
|
||||
var log = ""
|
||||
var result = 20
|
||||
|
||||
fun <T> id(value: T) = value
|
||||
|
||||
fun box(): String {
|
||||
result += if (id("true") == "true") {
|
||||
result += 10
|
||||
log += "true chosen"
|
||||
3
|
||||
}
|
||||
else {
|
||||
4
|
||||
}
|
||||
|
||||
assertEquals(23, result)
|
||||
assertEquals("true chosen", log)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+12
@@ -4768,6 +4768,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("switchLikeWhen.kt")
|
||||
public void testSwitchLikeWhen() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwFromCatch.kt")
|
||||
public void testThrowFromCatch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt");
|
||||
@@ -7679,6 +7685,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
|
||||
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classNaryGetSet.kt")
|
||||
public void testClassNaryGetSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");
|
||||
|
||||
@@ -4768,6 +4768,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("switchLikeWhen.kt")
|
||||
public void testSwitchLikeWhen() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("throwFromCatch.kt")
|
||||
public void testThrowFromCatch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt");
|
||||
@@ -7679,6 +7685,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
|
||||
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classNaryGetSet.kt")
|
||||
public void testClassNaryGetSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");
|
||||
|
||||
@@ -8838,6 +8838,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
|
||||
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classNaryGetSet.kt")
|
||||
public void testClassNaryGetSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");
|
||||
|
||||
+5
-1
@@ -91,7 +91,11 @@ object DefaultVariableAccessCase : VariableAccessCase() {
|
||||
getCapturedVarAccessor(functionRef)
|
||||
}
|
||||
else {
|
||||
functionRef
|
||||
functionRef.apply {
|
||||
if (isGetAccess()) {
|
||||
sideEffects = SideEffectKind.DEPENDS_ON_STATE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val localVariableDescriptor = resolvedCall.resultingDescriptor as? LocalVariableDescriptor
|
||||
|
||||
+18
-8
@@ -23,6 +23,7 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.reference.AccessTranslator;
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
@@ -33,8 +34,10 @@ import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleN
|
||||
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateRightExpression;
|
||||
|
||||
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
private JsExpression right;
|
||||
private AccessTranslator accessTranslator;
|
||||
private final JsExpression right;
|
||||
private final AccessTranslator accessTranslator;
|
||||
private final boolean rightExpressionTrivial;
|
||||
private final JsBlock rightBlock = new JsBlock();
|
||||
|
||||
@NotNull
|
||||
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
|
||||
@@ -46,10 +49,9 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
@NotNull TranslationContext context) {
|
||||
super(expression, context);
|
||||
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
right = translateRightExpression(context, expression, rightBlock);
|
||||
accessTranslator = createAccessTranslator(expression.getLeft(), !rightBlock.isEmpty());
|
||||
context.addStatementsToCurrentBlockFrom(rightBlock);
|
||||
rightExpressionTrivial = rightBlock.isEmpty();
|
||||
accessTranslator = createAccessTranslator(expression.getLeft(), !rightExpressionTrivial);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -62,7 +64,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateAsAssignmentOperation() {
|
||||
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context())) {
|
||||
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context()) && rightExpressionTrivial) {
|
||||
return translateAsPlainAssignmentOperation();
|
||||
}
|
||||
return translateAsAssignToCounterpart();
|
||||
@@ -71,14 +73,19 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
@NotNull
|
||||
private JsExpression translateAsAssignToCounterpart() {
|
||||
JsBinaryOperator operator = getCounterpartOperator();
|
||||
JsBinaryOperation counterpartOperation =
|
||||
new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
|
||||
JsExpression oldValue = accessTranslator.translateAsGet();
|
||||
if (!rightExpressionTrivial) {
|
||||
oldValue = context().defineTemporary(oldValue);
|
||||
}
|
||||
JsBinaryOperation counterpartOperation = new JsBinaryOperation(operator, oldValue, right);
|
||||
context().addStatementsToCurrentBlockFrom(rightBlock);
|
||||
return accessTranslator.translateAsSet(counterpartOperation);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsBinaryOperator getCounterpartOperator() {
|
||||
KtToken assignmentOperationToken = getOperationToken(expression);
|
||||
assert assignmentOperationToken instanceof KtSingleValueToken;
|
||||
assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(assignmentOperationToken);
|
||||
KtToken counterpartToken = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(assignmentOperationToken);
|
||||
assert OperatorTable.hasCorrespondingBinaryOperator(counterpartToken) :
|
||||
@@ -88,6 +95,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateAsPlainAssignmentOperation() {
|
||||
context().addStatementsToCurrentBlockFrom(rightBlock);
|
||||
JsBinaryOperator operator = getAssignmentOperator();
|
||||
return new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
|
||||
}
|
||||
@@ -95,6 +103,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
@NotNull
|
||||
private JsBinaryOperator getAssignmentOperator() {
|
||||
KtToken token = getOperationToken(expression);
|
||||
assert token instanceof KtSingleValueToken;
|
||||
assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(token);
|
||||
assert OperatorTable.hasCorrespondingBinaryOperator(token) :
|
||||
"Unsupported token encountered: " + token.toString();
|
||||
@@ -103,6 +112,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateAsPlainAssignment() {
|
||||
context().addStatementsToCurrentBlockFrom(rightBlock);
|
||||
return accessTranslator.translateAsSet(right);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user