JS: don't translate RHS of overloaded assignment operators twice. It can break compilation in some cases, for example, when there are lambdas in RHS.
Fix #KT-12808 #KT-12807
This commit is contained in:
@@ -120,4 +120,8 @@ public final class OperatorOverloadingTest extends SingleFileTranslationTest {
|
|||||||
public void testOverloadUnaryOperationsViaExtensionFunctions() throws Exception {
|
public void testOverloadUnaryOperationsViaExtensionFunctions() throws Exception {
|
||||||
fooBoxTest();
|
fooBoxTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testLambdaRhs() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-13
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.operation;
|
package org.jetbrains.kotlin.js.translate.operation;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -37,7 +36,6 @@ import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.isVariableRea
|
|||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getSimpleName;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getSimpleName;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.hasCorrespondingFunctionIntrinsic;
|
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.hasCorrespondingFunctionIntrinsic;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateRightExpression;
|
|
||||||
|
|
||||||
public abstract class AssignmentTranslator extends AbstractTranslator {
|
public abstract class AssignmentTranslator extends AbstractTranslator {
|
||||||
|
|
||||||
@@ -56,10 +54,7 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected final KtBinaryExpression expression;
|
protected final KtBinaryExpression expression;
|
||||||
protected final AccessTranslator accessTranslator;
|
|
||||||
protected final boolean isVariableReassignment;
|
protected final boolean isVariableReassignment;
|
||||||
@NotNull
|
|
||||||
protected final JsExpression right;
|
|
||||||
|
|
||||||
protected AssignmentTranslator(@NotNull KtBinaryExpression expression,
|
protected AssignmentTranslator(@NotNull KtBinaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
@@ -68,19 +63,16 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
|||||||
this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression);
|
this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression);
|
||||||
KtExpression left = expression.getLeft();
|
KtExpression left = expression.getLeft();
|
||||||
assert left != null : "No left-hand side: " + expression.getText();
|
assert left != null : "No left-hand side: " + expression.getText();
|
||||||
|
}
|
||||||
|
|
||||||
JsBlock rightBlock = new JsBlock();
|
protected final AccessTranslator createAccessTranslator(KtExpression left, boolean forceOrderOfEvaluation) {
|
||||||
this.right = translateRightExpression(context, expression, rightBlock);
|
if (isReferenceToBackingFieldFromConstructor(left, context())) {
|
||||||
|
|
||||||
if (isReferenceToBackingFieldFromConstructor(left, context)) {
|
|
||||||
KtSimpleNameExpression simpleName = getSimpleName(left);
|
KtSimpleNameExpression simpleName = getSimpleName(left);
|
||||||
assert simpleName != null;
|
assert simpleName != null;
|
||||||
this.accessTranslator = BackingFieldAccessTranslator.newInstance(simpleName, context);
|
return BackingFieldAccessTranslator.newInstance(simpleName, context());
|
||||||
} else {
|
} else {
|
||||||
this.accessTranslator = AccessTranslationUtils.getAccessTranslator(left, context(), !rightBlock.isEmpty());
|
return AccessTranslationUtils.getAccessTranslator(left, context(), forceOrderOfEvaluation);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.addStatementsToCurrentBlockFrom(rightBlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isReferenceToBackingFieldFromConstructor(
|
private static boolean isReferenceToBackingFieldFromConstructor(
|
||||||
|
|||||||
+10
-1
@@ -18,9 +18,11 @@ package org.jetbrains.kotlin.js.translate.operation;
|
|||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
|
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
|
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
|
import org.jetbrains.kotlin.js.translate.reference.AccessTranslator;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||||
import org.jetbrains.kotlin.lexer.KtToken;
|
import org.jetbrains.kotlin.lexer.KtToken;
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression;
|
import org.jetbrains.kotlin.psi.KtBinaryExpression;
|
||||||
@@ -29,9 +31,11 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
|||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar;
|
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar;
|
||||||
|
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateRightExpression;
|
||||||
|
|
||||||
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||||
|
private JsExpression right;
|
||||||
|
private AccessTranslator accessTranslator;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
|
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
|
||||||
@@ -42,6 +46,11 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
|||||||
private IntrinsicAssignmentTranslator(@NotNull KtBinaryExpression expression,
|
private IntrinsicAssignmentTranslator(@NotNull KtBinaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(expression, context);
|
super(expression, context);
|
||||||
|
|
||||||
|
JsBlock rightBlock = new JsBlock();
|
||||||
|
right = translateRightExpression(context, expression, rightBlock);
|
||||||
|
accessTranslator = createAccessTranslator(expression.getLeft(), !rightBlock.isEmpty());
|
||||||
|
context.addStatementsToCurrentBlockFrom(rightBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+11
-2
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.operation;
|
package org.jetbrains.kotlin.js.translate.operation;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
|
|
||||||
public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
|
public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
|
||||||
|
private boolean forceOrderOfEvaluation;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
|
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
|
||||||
@@ -52,11 +54,18 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression reassignment() {
|
private JsExpression reassignment() {
|
||||||
return accessTranslator.translateAsSet(overloadedMethodInvocation());
|
JsExpression newValue = overloadedMethodInvocation();
|
||||||
|
return createAccessTranslator(expression.getLeft(), forceOrderOfEvaluation).translateAsSet(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression overloadedMethodInvocation() {
|
private JsExpression overloadedMethodInvocation() {
|
||||||
return CallTranslator.translate(context(), resolvedCall, accessTranslator.translateAsGet());
|
JsBlock innerBlock = new JsBlock();
|
||||||
|
TranslationContext innerContext = context().innerBlock(innerBlock);
|
||||||
|
JsExpression oldValue = createAccessTranslator(expression.getLeft(), false).translateAsGet();
|
||||||
|
JsExpression result = CallTranslator.translate(innerContext, resolvedCall, oldValue);
|
||||||
|
forceOrderOfEvaluation = !innerBlock.isEmpty();
|
||||||
|
context().addStatementsToCurrentBlockFrom(innerBlock);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
var global = ""
|
||||||
|
|
||||||
|
fun log(message: String) {
|
||||||
|
global += message
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1(): String {
|
||||||
|
val list = mutableListOf<(Int) -> Unit>()
|
||||||
|
|
||||||
|
var result = ""
|
||||||
|
list += { log("<$it>") }
|
||||||
|
list += { result += "($it)" }
|
||||||
|
list += { result += "[$it]"; result += "{$it}" }
|
||||||
|
|
||||||
|
for(f in list) f(1)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals("(1)[1]{1}", test1())
|
||||||
|
assertEquals(global, "<1>")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user