diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 80becf74009..06b7a6879ad 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -557,7 +557,7 @@ class Fir2IrVisitor( functionCall.calleeReference.name == OperatorNameConventions.SET && functionCall.calleeReference.source?.kind == KtFakeSourceElementKind.ArrayAccessNameReference ) { - return convertToIrArrayAccessDynamicCall(functionCall) + return convertToIrArraySetDynamicCall(functionCall) } return convertToIrCall(functionCall, dynamicOperator = null) } @@ -578,25 +578,24 @@ class Fir2IrVisitor( ) } - private fun convertToIrArrayAccessDynamicCall(functionCall: FirFunctionCall): IrExpression { - val explicitReceiverExpression = convertToIrCall( - functionCall, dynamicOperator = IrDynamicOperator.ARRAY_ACCESS - ) - if (explicitReceiverExpression is IrDynamicOperatorExpression) { - explicitReceiverExpression.arguments.removeLast() + private fun convertToIrArraySetDynamicCall(functionCall: FirFunctionCall): IrExpression { + // `functionCall` has the form of `myDynamic.set(key1, key2, ..., newValue)`. + // The resulting IR expects something like `myDynamic.ARRAY_ACCESS(key1, key2, ...).EQ(newValue)`. + // Instead of constructing a `FirFunctionCall` for `get()` (the true `ARRAY_ACCESS`), and a new + // call for `set()` (`EQ`), let's convert the whole thing as `ARRAY_ACCESS`, including + // `newValue`, and then manually move it to a newly constructed EQ call. + val arraySetAsGenericDynamicAccess = convertToIrCall(functionCall, IrDynamicOperator.ARRAY_ACCESS) as? IrDynamicOperatorExpression + ?: error("Converting dynamic array access should have resulted in IrDynamicOperatorExpression") + val arraySetNewValue = arraySetAsGenericDynamicAccess.arguments.removeLast() + return IrDynamicOperatorExpressionImpl( + arraySetAsGenericDynamicAccess.startOffset, + arraySetAsGenericDynamicAccess.endOffset, + arraySetAsGenericDynamicAccess.type, + IrDynamicOperator.EQ, + ).apply { + receiver = arraySetAsGenericDynamicAccess + arguments.add(arraySetNewValue) } - val result = callGenerator.convertToIrCall( - functionCall, functionCall.resolvedType, explicitReceiverExpression, - dynamicOperator = IrDynamicOperator.EQ - ) - if (result is IrDynamicOperatorExpression) { - val arguments = result.arguments - arguments[0] = arguments[arguments.lastIndex] - while (arguments.size > 1) { - arguments.removeLast() - } - } - return result } override fun visitFunctionCall(functionCall: FirFunctionCall, data: Any?): IrExpression = whileAnalysing(session, functionCall) { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java index 820c4b48bcc..44056278440 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsBoxTestGenerated.java @@ -1738,6 +1738,12 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest { runTest("js/js.translator/testData/box/dynamic/compareTo.kt"); } + @Test + @TestMetadata("dynamicArraySetWithLambda.kt") + public void testDynamicArraySetWithLambda() throws Exception { + runTest("js/js.translator/testData/box/dynamic/dynamicArraySetWithLambda.kt"); + } + @Test @TestMetadata("equals.kt") public void testEquals() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java index 393706893c0..19e9988a0e5 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java @@ -1738,6 +1738,12 @@ public class FirJsES6BoxTestGenerated extends AbstractFirJsES6BoxTest { runTest("js/js.translator/testData/box/dynamic/compareTo.kt"); } + @Test + @TestMetadata("dynamicArraySetWithLambda.kt") + public void testDynamicArraySetWithLambda() throws Exception { + runTest("js/js.translator/testData/box/dynamic/dynamicArraySetWithLambda.kt"); + } + @Test @TestMetadata("equals.kt") public void testEquals() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java index bbdb1ee36b9..8b9998e17bb 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java @@ -1738,6 +1738,12 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/dynamic/compareTo.kt"); } + @Test + @TestMetadata("dynamicArraySetWithLambda.kt") + public void testDynamicArraySetWithLambda() throws Exception { + runTest("js/js.translator/testData/box/dynamic/dynamicArraySetWithLambda.kt"); + } + @Test @TestMetadata("equals.kt") public void testEquals() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index 1442e363060..dfac6509e97 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -1738,6 +1738,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/dynamic/compareTo.kt"); } + @Test + @TestMetadata("dynamicArraySetWithLambda.kt") + public void testDynamicArraySetWithLambda() throws Exception { + runTest("js/js.translator/testData/box/dynamic/dynamicArraySetWithLambda.kt"); + } + @Test @TestMetadata("equals.kt") public void testEquals() throws Exception { diff --git a/js/js.translator/testData/box/dynamic/dynamicArraySetWithLambda.kt b/js/js.translator/testData/box/dynamic/dynamicArraySetWithLambda.kt new file mode 100644 index 00000000000..19dff4612b4 --- /dev/null +++ b/js/js.translator/testData/box/dynamic/dynamicArraySetWithLambda.kt @@ -0,0 +1,10 @@ +// ISSUE: KT-63593 +// WITH_STDLIB + +fun jso(): T = mutableMapOf() as T + +fun box(): String { + val obj = jso() + obj["a"] = run { "OK" } + return obj["a"] +}