Skip to content

Commit 40e00a6

Browse files
Alexey AndreevAlexey Andreev
authored andcommitted
JS: fix translation of augmented assignment when RHS changes value of LHS
1 parent be19678 commit 40e00a6

File tree

7 files changed

+77
-13
lines changed

7 files changed

+77
-13
lines changed

compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// WITH_RUNTIME
22
// NO_INTERCEPT_RESUME_TESTS
33

4-
// TODO: fix bug in JVM backend and remove this directive
5-
// TARGET_BACKEND: JS
6-
74
class Controller {
85
var result = ""
96

@@ -29,7 +26,7 @@ fun box(): String {
2926
}
3027
}
3128
}
32-
if (value != "A;[B][C]!") return "fail: suspend as if condition: $value"
29+
if (value != "A;B]C]!") return "fail: suspend as if condition: $value"
3330

3431
return "OK"
3532
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// WITH_RUNTIME
2+
import kotlin.test.*
3+
4+
var log = ""
5+
var result = 20
6+
7+
fun <T> id(value: T) = value
8+
9+
fun box(): String {
10+
result += if (id("true") == "true") {
11+
result += 10
12+
log += "true chosen"
13+
3
14+
}
15+
else {
16+
4
17+
}
18+
19+
assertEquals(23, result)
20+
assertEquals("true chosen", log)
21+
22+
return "OK"
23+
}

compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4768,6 +4768,12 @@ public void testIfStatement() throws Exception {
47684768
doTest(fileName);
47694769
}
47704770

4771+
@TestMetadata("switchLikeWhen.kt")
4772+
public void testSwitchLikeWhen() throws Exception {
4773+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt");
4774+
doTest(fileName);
4775+
}
4776+
47714777
@TestMetadata("throwFromCatch.kt")
47724778
public void testThrowFromCatch() throws Exception {
47734779
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt");
@@ -7679,6 +7685,12 @@ public void testAssignPlusOnSmartCast() throws Exception {
76797685
doTest(fileName);
76807686
}
76817687

7688+
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
7689+
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
7690+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
7691+
doTest(fileName);
7692+
}
7693+
76827694
@TestMetadata("classNaryGetSet.kt")
76837695
public void testClassNaryGetSet() throws Exception {
76847696
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");

compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4768,6 +4768,12 @@ public void testIfStatement() throws Exception {
47684768
doTest(fileName);
47694769
}
47704770

4771+
@TestMetadata("switchLikeWhen.kt")
4772+
public void testSwitchLikeWhen() throws Exception {
4773+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt");
4774+
doTest(fileName);
4775+
}
4776+
47714777
@TestMetadata("throwFromCatch.kt")
47724778
public void testThrowFromCatch() throws Exception {
47734779
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt");
@@ -7679,6 +7685,12 @@ public void testAssignPlusOnSmartCast() throws Exception {
76797685
doTest(fileName);
76807686
}
76817687

7688+
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
7689+
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
7690+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
7691+
doTest(fileName);
7692+
}
7693+
76827694
@TestMetadata("classNaryGetSet.kt")
76837695
public void testClassNaryGetSet() throws Exception {
76847696
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");

js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8838,6 +8838,12 @@ public void testAssignPlusOnSmartCast() throws Exception {
88388838
doTest(fileName);
88398839
}
88408840

8841+
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
8842+
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
8843+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
8844+
doTest(fileName);
8845+
}
8846+
88418847
@TestMetadata("classNaryGetSet.kt")
88428848
public void testClassNaryGetSet() throws Exception {
88438849
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");

js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ object DefaultVariableAccessCase : VariableAccessCase() {
9191
getCapturedVarAccessor(functionRef)
9292
}
9393
else {
94-
functionRef
94+
functionRef.apply {
95+
if (isGetAccess()) {
96+
sideEffects = SideEffectKind.DEPENDS_ON_STATE
97+
}
98+
}
9599
}
96100

97101
val localVariableDescriptor = resolvedCall.resultingDescriptor as? LocalVariableDescriptor

js/js.translator/src/org/jetbrains/kotlin/js/translate/operation/IntrinsicAssignmentTranslator.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.jetbrains.annotations.NotNull;
2424
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
2525
import org.jetbrains.kotlin.js.translate.reference.AccessTranslator;
26+
import org.jetbrains.kotlin.lexer.KtSingleValueToken;
2627
import org.jetbrains.kotlin.lexer.KtToken;
2728
import org.jetbrains.kotlin.psi.KtBinaryExpression;
2829
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
@@ -33,8 +34,10 @@
3334
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateRightExpression;
3435

3536
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
36-
private JsExpression right;
37-
private AccessTranslator accessTranslator;
37+
private final JsExpression right;
38+
private final AccessTranslator accessTranslator;
39+
private final boolean rightExpressionTrivial;
40+
private final JsBlock rightBlock = new JsBlock();
3841

3942
@NotNull
4043
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
@@ -46,10 +49,9 @@ private IntrinsicAssignmentTranslator(@NotNull KtBinaryExpression expression,
4649
@NotNull TranslationContext context) {
4750
super(expression, context);
4851

49-
JsBlock rightBlock = new JsBlock();
5052
right = translateRightExpression(context, expression, rightBlock);
51-
accessTranslator = createAccessTranslator(expression.getLeft(), !rightBlock.isEmpty());
52-
context.addStatementsToCurrentBlockFrom(rightBlock);
53+
rightExpressionTrivial = rightBlock.isEmpty();
54+
accessTranslator = createAccessTranslator(expression.getLeft(), !rightExpressionTrivial);
5355
}
5456

5557
@NotNull
@@ -62,7 +64,7 @@ private JsExpression translate() {
6264

6365
@NotNull
6466
private JsExpression translateAsAssignmentOperation() {
65-
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context())) {
67+
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context()) && rightExpressionTrivial) {
6668
return translateAsPlainAssignmentOperation();
6769
}
6870
return translateAsAssignToCounterpart();
@@ -71,14 +73,19 @@ private JsExpression translateAsAssignmentOperation() {
7173
@NotNull
7274
private JsExpression translateAsAssignToCounterpart() {
7375
JsBinaryOperator operator = getCounterpartOperator();
74-
JsBinaryOperation counterpartOperation =
75-
new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
76+
JsExpression oldValue = accessTranslator.translateAsGet();
77+
if (!rightExpressionTrivial) {
78+
oldValue = context().defineTemporary(oldValue);
79+
}
80+
JsBinaryOperation counterpartOperation = new JsBinaryOperation(operator, oldValue, right);
81+
context().addStatementsToCurrentBlockFrom(rightBlock);
7682
return accessTranslator.translateAsSet(counterpartOperation);
7783
}
7884

7985
@NotNull
8086
private JsBinaryOperator getCounterpartOperator() {
8187
KtToken assignmentOperationToken = getOperationToken(expression);
88+
assert assignmentOperationToken instanceof KtSingleValueToken;
8289
assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(assignmentOperationToken);
8390
KtToken counterpartToken = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(assignmentOperationToken);
8491
assert OperatorTable.hasCorrespondingBinaryOperator(counterpartToken) :
@@ -88,13 +95,15 @@ private JsBinaryOperator getCounterpartOperator() {
8895

8996
@NotNull
9097
private JsExpression translateAsPlainAssignmentOperation() {
98+
context().addStatementsToCurrentBlockFrom(rightBlock);
9199
JsBinaryOperator operator = getAssignmentOperator();
92100
return new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
93101
}
94102

95103
@NotNull
96104
private JsBinaryOperator getAssignmentOperator() {
97105
KtToken token = getOperationToken(expression);
106+
assert token instanceof KtSingleValueToken;
98107
assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(token);
99108
assert OperatorTable.hasCorrespondingBinaryOperator(token) :
100109
"Unsupported token encountered: " + token.toString();
@@ -103,6 +112,7 @@ private JsBinaryOperator getAssignmentOperator() {
103112

104113
@NotNull
105114
private JsExpression translateAsPlainAssignment() {
115+
context().addStatementsToCurrentBlockFrom(rightBlock);
106116
return accessTranslator.translateAsSet(right);
107117
}
108118
}

0 commit comments

Comments
 (0)