From b925404e11f82dd263b7a6bf924dc84cd579e8fc Mon Sep 17 00:00:00 2001 From: Artem Kobzar Date: Wed, 16 Aug 2023 08:40:21 +0000 Subject: [PATCH] [K/JS] Fix autoboxing for inlined function ^KT-60785 Fixed --- .../kotlin/ir/backend/js/JsLoweringPhases.kt | 2 +- .../backend/js/lower/AutoboxingTransformer.kt | 20 +++++++++-- .../kotlin/js/test/BoxJsTestGenerated.java | 6 ++++ .../js/test/fir/FirJsBoxTestGenerated.java | 6 ++++ .../js/test/ir/IrBoxJsES6TestGenerated.java | 6 ++++ .../js/test/ir/IrBoxJsTestGenerated.java | 6 ++++ .../boxingUnboxingInsideTheSuspendFunction.kt | 35 +++++++++++++++++++ 7 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index 84ecf0f5ea068..88eb5b1998576 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -727,7 +727,7 @@ private val inlineClassUsageLoweringPhase = makeBodyLoweringPhase( ) private val autoboxingTransformerPhase = makeBodyLoweringPhase( - ::AutoboxingTransformer, + { AutoboxingTransformer(it, shouldCalculateActualTypeForInlinedFunction = true) }, name = "AutoboxingTransformer", description = "Insert box/unbox intrinsics" ) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt index 55de84c67f438..dc236f7bbdf23 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt @@ -31,7 +31,10 @@ import org.jetbrains.kotlin.ir.util.render // Copied and adapted from Kotlin/Native -abstract class AbstractValueUsageLowering(val context: JsCommonBackendContext) : AbstractValueUsageTransformer(context.irBuiltIns), +abstract class AbstractValueUsageLowering( + val context: JsCommonBackendContext, + private val shouldCalculateActualTypeForInlinedFunction: Boolean = false +) : AbstractValueUsageTransformer(context.irBuiltIns), BodyLoweringPass { val icUtils = context.inlineClassesUtils @@ -52,11 +55,19 @@ abstract class AbstractValueUsageLowering(val context: JsCommonBackendContext) : abstract fun IrExpression.useExpressionAsType(actualType: IrType, expectedType: IrType): IrExpression - protected fun IrExpression.getActualType() = when (this) { + protected fun IrExpression.getActualType(): IrType = when (this) { is IrConstructorCall -> symbol.owner.returnType is IrCall -> symbol.owner.realOverrideTarget.returnType is IrGetField -> this.symbol.owner.type + is IrInlinedFunctionBlock -> { + if (shouldCalculateActualTypeForInlinedFunction) { + inlineCall.getActualType() + } else { + this.type + } + } + is IrTypeOperatorCall -> { if (operator == IrTypeOperator.REINTERPRET_CAST) { this.typeOperand @@ -120,7 +131,10 @@ abstract class AbstractValueUsageLowering(val context: JsCommonBackendContext) : ) } -class AutoboxingTransformer(context: JsCommonBackendContext) : AbstractValueUsageLowering(context) { +class AutoboxingTransformer( + context: JsCommonBackendContext, + shouldCalculateActualTypeForInlinedFunction: Boolean = false +) : AbstractValueUsageLowering(context, shouldCalculateActualTypeForInlinedFunction) { private var processingReturnStack = mutableListOf() private fun IrExpression.useReturnableExpressionAsType(expectedType: IrType): IrExpression { 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 a82c916fc0880..239bef27c60d4 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 @@ -796,6 +796,12 @@ public void testAllFilesPresentInCoroutines() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/coroutines"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true); } + @Test + @TestMetadata("boxingUnboxingInsideTheSuspendFunction.kt") + public void testBoxingUnboxingInsideTheSuspendFunction() throws Exception { + runTest("js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt"); + } + @Test @TestMetadata("debugStatement.kt") public void testDebugStatement() throws Exception { 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 ca056440fa28c..62ec9fb1d09c8 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 @@ -860,6 +860,12 @@ public void testAllFilesPresentInCoroutines() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/coroutines"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); } + @Test + @TestMetadata("boxingUnboxingInsideTheSuspendFunction.kt") + public void testBoxingUnboxingInsideTheSuspendFunction() throws Exception { + runTest("js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt"); + } + @Test @TestMetadata("debugStatement.kt") public void testDebugStatement() 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 a8015be1f760d..f38a26ddbb1b2 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 @@ -860,6 +860,12 @@ public void testAllFilesPresentInCoroutines() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/coroutines"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } + @Test + @TestMetadata("boxingUnboxingInsideTheSuspendFunction.kt") + public void testBoxingUnboxingInsideTheSuspendFunction() throws Exception { + runTest("js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt"); + } + @Test @TestMetadata("debugStatement.kt") public void testDebugStatement() 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 116c84b65c322..b3d1ea80cdc07 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 @@ -860,6 +860,12 @@ public void testAllFilesPresentInCoroutines() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/coroutines"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true); } + @Test + @TestMetadata("boxingUnboxingInsideTheSuspendFunction.kt") + public void testBoxingUnboxingInsideTheSuspendFunction() throws Exception { + runTest("js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt"); + } + @Test @TestMetadata("debugStatement.kt") public void testDebugStatement() throws Exception { diff --git a/js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt b/js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt new file mode 100644 index 0000000000000..0b1284924bb9b --- /dev/null +++ b/js/js.translator/testData/box/coroutines/boxingUnboxingInsideTheSuspendFunction.kt @@ -0,0 +1,35 @@ +// WITH_STDLIB +// EXPECTED_REACHABLE_NODES: 1292 +// KT-60785 + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +value class SomeValue(val a: String) { + override fun toString() = when (a) { + "fa" -> "O" + "il" -> "K" + else -> "" + } +} + +suspend fun foo() = mapOf(SomeValue("fa") to SomeValue("il")) + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(object : Continuation { + override val context = EmptyCoroutineContext + override fun resumeWith(result: Result) {} + }) +} + +fun box(): String { + var result = "" + + builder { + for ((k, v) in foo()) { + result += "$k$v" + } + } + + return result +}