From 529944fe9ca74370b032b6db891ad2b38df77301 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Tue, 23 Nov 2021 15:15:33 +0100 Subject: [PATCH] [JVM_IR] Fix inline class default method codegen. Do not coroutine transform static inline class replacements that forward to a default interface suspend method. No boxing has to take place on return (as the default interface method always boxes) so we can simply forward the call. ^KT-49645 Fixed --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++++ .../backend/jvm/codegen/CoroutineCodegen.kt | 15 ++++++---- .../codegen/box/coroutines/kt49645.kt | 30 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++++ .../LightAnalysisModeTestGenerated.java | 5 ++++ .../NativeExtBlackBoxTestGenerated.java | 6 ++++ 7 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/kt49645.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index f9d457caa16..d91a48d2434 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -9828,6 +9828,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/coroutines/kt49168.kt"); } + @Test + @TestMetadata("kt49645.kt") + public void testKt49645() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/kt49645.kt"); + } + @Test @TestMetadata("lastExpressionIsLoop.kt") public void testLastExpressionIsLoop() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index 12fa1cd5c23..14078fa04a0 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -21,10 +21,7 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.file -import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.isSuspend -import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.Type @@ -147,7 +144,15 @@ private val BRIDGE_ORIGINS = setOf( // These functions contain a single `suspend` tail call, the value of which should be returned as is // (i.e. if it's an unboxed inline class value, it should remain unboxed). internal fun IrFunction.isNonBoxingSuspendDelegation(): Boolean = - origin in BRIDGE_ORIGINS || isMultifileBridge() || isBridgeToSuspendImplMethod() + origin in BRIDGE_ORIGINS || + isMultifileBridge() || + isBridgeToSuspendImplMethod() || + isStaticInlineClassReplacementForDefaultInterfaceMethod() + +// Suspend static inline class replacements for fake overrides have to be for interface methods as inline classes cannot have a +// non-Object super type. +fun IrFunction.isStaticInlineClassReplacementForDefaultInterfaceMethod(): Boolean = + isStaticInlineClassReplacement && this is IrSimpleFunction && (attributeOwnerId as IrSimpleFunction).isFakeOverride fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isNonBoxingSuspendDelegation() && // These functions also contain a single `suspend` tail call, but if it returns an unboxed inline class value, diff --git a/compiler/testData/codegen/box/coroutines/kt49645.kt b/compiler/testData/codegen/box/coroutines/kt49645.kt new file mode 100644 index 00000000000..3b3708be7a9 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/kt49645.kt @@ -0,0 +1,30 @@ +// WITH_STDLIB +// WITH_COROUTINES +// TARGET_BACKEND: JVM + +import helpers.* +import kotlin.coroutines.* + +interface Cont1 { + suspend fun flaf() = "O" + + suspend fun toResult(): Result { + val x = flaf() + return Result.success(x + "K") + } +} + +@JvmInline +private value class ContImpl(val a: String) : Cont1 + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun box(): String { + var result = "FAIL" + builder { + result = ContImpl("A").toResult().getOrThrow() + } + return result +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 075b1ec50a0..5b5d781ca79 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -9750,6 +9750,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/kt49168.kt"); } + @Test + @TestMetadata("kt49645.kt") + public void testKt49645() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/kt49645.kt"); + } + @Test @TestMetadata("lastExpressionIsLoop.kt") public void testLastExpressionIsLoop() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index c5a2f0a595f..0c5b6f099eb 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -9828,6 +9828,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/kt49168.kt"); } + @Test + @TestMetadata("kt49645.kt") + public void testKt49645() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/kt49645.kt"); + } + @Test @TestMetadata("lastExpressionIsLoop.kt") public void testLastExpressionIsLoop() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index e2a65fc09f9..50313639d3b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7638,6 +7638,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/kt46813.kt"); } + @TestMetadata("kt49645.kt") + public void testKt49645() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/kt49645.kt"); + } + @TestMetadata("lastExpressionIsLoop.kt") public void testLastExpressionIsLoop() throws Exception { runTest("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt"); diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java index 452ce4e0606..4836ad4e12f 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeExtBlackBoxTestGenerated.java @@ -7730,6 +7730,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest { runTest("compiler/testData/codegen/box/coroutines/kt49168.kt"); } + @Test + @TestMetadata("kt49645.kt") + public void testKt49645() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/kt49645.kt"); + } + @Test @TestMetadata("lastExpressionIsLoop.kt") public void testLastExpressionIsLoop() throws Exception {