From 833c8b2cd41269b8c4e7e2ad2a55ee29457fb0f1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Tue, 15 Aug 2023 14:18:55 +0200 Subject: [PATCH] [Wasm] Fix transforming setField in an inline class constructor body IrSetField was transformed to its value to preserve side effects This transformation produced invalid IR in cases where IrSetField used in Unit-returning expression context. This commit fixes it by producing Unit-typed expression ^KT-59084 Fixed --- .../lower/InlineClassDeclarationLowering.kt | 11 ++++++++++- .../codegen/boxWasmJsInterop/kt59084.kt | 18 ++++++++++++++++++ ...rWasmCodegenWasmJsInteropTestGenerated.java | 6 ++++++ ...1WasmCodegenWasmJsInteropTestGenerated.java | 6 ++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/boxWasmJsInterop/kt59084.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt index 19c1040b5b5..d7df1017bc3 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.DeclarationTransformer import org.jetbrains.kotlin.backend.common.getOrPut +import org.jetbrains.kotlin.backend.common.ir.isPure import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* @@ -105,7 +106,15 @@ class InlineClassLowering(val context: CommonBackendContext) { } expression.transformChildrenVoid() if (isMemberFieldSet) { - return expression.value + return builder.irBlock { + if (!expression.value.isPure(true)) { + // Preserving side effects + +expression.value + // Adding empty block to provide Unit value. + // This is useful when original IrSetField is the last statement in a Unit-returning block. + +builder.irBlock {} + } + } } return expression } diff --git a/compiler/testData/codegen/boxWasmJsInterop/kt59084.kt b/compiler/testData/codegen/boxWasmJsInterop/kt59084.kt new file mode 100644 index 00000000000..fbc9b39045f --- /dev/null +++ b/compiler/testData/codegen/boxWasmJsInterop/kt59084.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: WASM + +inline class JsDynamic(val value: JsAny?) + +val JsAny?.jsDyn: JsDynamic get() = JsDynamic(this) + +fun test(): Boolean { + val jsDynamic: JsAny? = 1.toJsNumber() + val jsDyn = jsDynamic.jsDyn + return jsDyn.value == jsDynamic +} + +fun box(): String { + if (!test()) { + return "Fail" + } + return "OK" +} diff --git a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/FirWasmCodegenWasmJsInteropTestGenerated.java b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/FirWasmCodegenWasmJsInteropTestGenerated.java index 18348e29e1c..323118c10d1 100644 --- a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/FirWasmCodegenWasmJsInteropTestGenerated.java +++ b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/FirWasmCodegenWasmJsInteropTestGenerated.java @@ -121,6 +121,12 @@ public class FirWasmCodegenWasmJsInteropTestGenerated extends AbstractFirWasmCod runTest("compiler/testData/codegen/boxWasmJsInterop/kt59082.kt"); } + @Test + @TestMetadata("kt59084.kt") + public void testKt59084() throws Exception { + runTest("compiler/testData/codegen/boxWasmJsInterop/kt59084.kt"); + } + @Test @TestMetadata("lambdaAdapterNameClash.kt") public void testLambdaAdapterNameClash() throws Exception { diff --git a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/K1WasmCodegenWasmJsInteropTestGenerated.java b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/K1WasmCodegenWasmJsInteropTestGenerated.java index 376ff24c2a6..1b292b442a5 100644 --- a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/K1WasmCodegenWasmJsInteropTestGenerated.java +++ b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/K1WasmCodegenWasmJsInteropTestGenerated.java @@ -121,6 +121,12 @@ public class K1WasmCodegenWasmJsInteropTestGenerated extends AbstractK1WasmCodeg runTest("compiler/testData/codegen/boxWasmJsInterop/kt59082.kt"); } + @Test + @TestMetadata("kt59084.kt") + public void testKt59084() throws Exception { + runTest("compiler/testData/codegen/boxWasmJsInterop/kt59084.kt"); + } + @Test @TestMetadata("lambdaAdapterNameClash.kt") public void testLambdaAdapterNameClash() throws Exception {