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 {
|
||||
fooBoxTest();
|
||||
}
|
||||
|
||||
public void testLambdaRhs() throws Exception {
|
||||
checkFooBoxIsOk();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-13
@@ -16,7 +16,6 @@
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
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.isAssignment;
|
||||
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 {
|
||||
|
||||
@@ -56,10 +54,7 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
protected final KtBinaryExpression expression;
|
||||
protected final AccessTranslator accessTranslator;
|
||||
protected final boolean isVariableReassignment;
|
||||
@NotNull
|
||||
protected final JsExpression right;
|
||||
|
||||
protected AssignmentTranslator(@NotNull KtBinaryExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
@@ -68,19 +63,16 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
||||
this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression);
|
||||
KtExpression left = expression.getLeft();
|
||||
assert left != null : "No left-hand side: " + expression.getText();
|
||||
}
|
||||
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
this.right = translateRightExpression(context, expression, rightBlock);
|
||||
|
||||
if (isReferenceToBackingFieldFromConstructor(left, context)) {
|
||||
protected final AccessTranslator createAccessTranslator(KtExpression left, boolean forceOrderOfEvaluation) {
|
||||
if (isReferenceToBackingFieldFromConstructor(left, context())) {
|
||||
KtSimpleNameExpression simpleName = getSimpleName(left);
|
||||
assert simpleName != null;
|
||||
this.accessTranslator = BackingFieldAccessTranslator.newInstance(simpleName, context);
|
||||
return BackingFieldAccessTranslator.newInstance(simpleName, context());
|
||||
} else {
|
||||
this.accessTranslator = AccessTranslationUtils.getAccessTranslator(left, context(), !rightBlock.isEmpty());
|
||||
return AccessTranslationUtils.getAccessTranslator(left, context(), forceOrderOfEvaluation);
|
||||
}
|
||||
|
||||
context.addStatementsToCurrentBlockFrom(rightBlock);
|
||||
}
|
||||
|
||||
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.JsBinaryOperator;
|
||||
import com.google.dart.compiler.backend.js.ast.JsBlock;
|
||||
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.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
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.isAssignment;
|
||||
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 {
|
||||
|
||||
private JsExpression right;
|
||||
private AccessTranslator accessTranslator;
|
||||
|
||||
@NotNull
|
||||
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
|
||||
@@ -42,6 +46,11 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||
private IntrinsicAssignmentTranslator(@NotNull KtBinaryExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
super(expression, context);
|
||||
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
right = translateRightExpression(context, expression, rightBlock);
|
||||
accessTranslator = createAccessTranslator(expression.getLeft(), !rightBlock.isEmpty());
|
||||
context.addStatementsToCurrentBlockFrom(rightBlock);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+11
-2
@@ -16,6 +16,7 @@
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
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;
|
||||
|
||||
public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
|
||||
private boolean forceOrderOfEvaluation;
|
||||
|
||||
@NotNull
|
||||
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
|
||||
@@ -52,11 +54,18 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
|
||||
|
||||
@NotNull
|
||||
private JsExpression reassignment() {
|
||||
return accessTranslator.translateAsSet(overloadedMethodInvocation());
|
||||
JsExpression newValue = overloadedMethodInvocation();
|
||||
return createAccessTranslator(expression.getLeft(), forceOrderOfEvaluation).translateAsSet(newValue);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
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