From 26487d283d3534a5c227845de491a08c5a6388e0 Mon Sep 17 00:00:00 2001 From: Anton Bannykh <anton.bannykh@jetbrains.com> Date: Fri, 15 Apr 2022 21:01:43 +0300 Subject: [PATCH] JS IR: materialize Unit in lambdas ^KT-52010 fixed (cherry picked from commit 281e381223eeb5957fac93436413639617976636) --- .../lower/InteropCallableReferenceLowering.kt | 6 ++++ .../kotlin/js/test/BoxJsTestGenerated.java | 12 +++++++ .../js/test/ir/IrBoxJsTestGenerated.java | 12 +++++++ .../expression/function/lambdaReturnValue.kt | 35 +++++++++++++++++++ .../testData/box/regression/kt52010.kt | 22 ++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 js/js.translator/testData/box/expression/function/lambdaReturnValue.kt create mode 100644 js/js.translator/testData/box/regression/kt52010.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/InteropCallableReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/InteropCallableReferenceLowering.kt index a72702611745f..7b4c60df08c4d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/InteropCallableReferenceLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/InteropCallableReferenceLowering.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -147,6 +148,11 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo // Fix parents of declarations inside body body.patchDeclarationParents(lambdaDeclaration) + if (invokeFun.returnType.isUnit()) { + val unitValue = JsIrBuilder.buildGetObjectValue(context.irBuiltIns.unitType, context.irBuiltIns.unitClass) + (body as IrBlockBody).statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.nothingType, lambdaDeclaration.symbol, unitValue)) + } + return body as IrBlockBody } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java index d0d93fdbbac85..41e9a478865b0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java @@ -2947,6 +2947,12 @@ public void testLambdaOrLocalFunInsideEnumMethod() throws Exception { runTest("js/js.translator/testData/box/expression/function/lambdaOrLocalFunInsideEnumMethod.kt"); } + @Test + @TestMetadata("lambdaReturnValue.kt") + public void testLambdaReturnValue() throws Exception { + runTest("js/js.translator/testData/box/expression/function/lambdaReturnValue.kt"); + } + @Test @TestMetadata("localExtFunction.kt") public void testLocalExtFunction() throws Exception { @@ -8612,6 +8618,12 @@ public void testKt2470() throws Exception { runTest("js/js.translator/testData/box/regression/kt2470.kt"); } + @Test + @TestMetadata("kt52010.kt") + public void testKt52010() throws Exception { + runTest("js/js.translator/testData/box/regression/kt52010.kt"); + } + @Test @TestMetadata("tmpInsidePrimaryConstructor.kt") public void testTmpInsidePrimaryConstructor() 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 22bc69df2cee4..a16b0f55d607c 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 @@ -3337,6 +3337,12 @@ public void testLambdaOrLocalFunInsideEnumMethod() throws Exception { runTest("js/js.translator/testData/box/expression/function/lambdaOrLocalFunInsideEnumMethod.kt"); } + @Test + @TestMetadata("lambdaReturnValue.kt") + public void testLambdaReturnValue() throws Exception { + runTest("js/js.translator/testData/box/expression/function/lambdaReturnValue.kt"); + } + @Test @TestMetadata("localExtFunction.kt") public void testLocalExtFunction() throws Exception { @@ -9002,6 +9008,12 @@ public void testKt2470() throws Exception { runTest("js/js.translator/testData/box/regression/kt2470.kt"); } + @Test + @TestMetadata("kt52010.kt") + public void testKt52010() throws Exception { + runTest("js/js.translator/testData/box/regression/kt52010.kt"); + } + @Test @TestMetadata("tmpInsidePrimaryConstructor.kt") public void testTmpInsidePrimaryConstructor() throws Exception { diff --git a/js/js.translator/testData/box/expression/function/lambdaReturnValue.kt b/js/js.translator/testData/box/expression/function/lambdaReturnValue.kt new file mode 100644 index 0000000000000..9809cce2756f0 --- /dev/null +++ b/js/js.translator/testData/box/expression/function/lambdaReturnValue.kt @@ -0,0 +1,35 @@ +// EXPECTED_REACHABLE_NODES: 1285 + +fun <T> rawReturnValue(fn: () -> T): Any { + return fn() as Any +} + +fun unitFun() {} + +fun charFun(): Char = 'a' + +value class VC(val v: Int) + +fun vcFun(): VC = VC(1) + + + +fun box(): String { + if (rawReturnValue { unitFun() } != Unit) return "fail1.1" + if (rawReturnValue<Unit> { unitFun() } != Unit) return "fail1.2" + if (rawReturnValue<Any> { unitFun() } != Unit) return "fail1.3" + + val boxedA: Any = 'a' + + if (rawReturnValue { charFun() } != boxedA) return "fail2.1" + if (rawReturnValue<Char> { charFun() } != boxedA) return "fail2.2" + if (rawReturnValue<Any> { charFun() } != boxedA) return "fail2.3" + + val boxed1: Any = VC(1) + + if (rawReturnValue { vcFun() } != boxed1) return "fail3.1" + if (rawReturnValue<VC> { vcFun() } != boxed1) return "fail3.2" + if (rawReturnValue<Any> { vcFun() } != boxed1) return "fail3.3" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/regression/kt52010.kt b/js/js.translator/testData/box/regression/kt52010.kt new file mode 100644 index 0000000000000..706e1ccad3e16 --- /dev/null +++ b/js/js.translator/testData/box/regression/kt52010.kt @@ -0,0 +1,22 @@ +// EXPECTED_REACHABLE_NODES: 1274 + +fun box(): String { + instance = Holder() + instance?.applyAndRet<Unit> { sideEffect("left") } ?: sideEffect("right") + + if (log == "left") return "OK" else return "fail: $log" +} + +var log = "" + +fun sideEffect(msg: String) { + log += msg +} + +var instance: Holder? = null + +class Holder() { + fun <T> applyAndRet(block: () -> T): T { + return block() + } +}