From 541f6b0c886005fa4a6dce248dbfb96c8dc4195a Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Wed, 12 Jan 2022 15:23:56 +0300 Subject: [PATCH] [K/N] Fix handling of legacy suspend-function superclass ^KT-50737 --- .../lower/AbstractSuspendFunctionsLowering.kt | 8 ++- .../backend.native/tests/build.gradle | 5 ++ .../tests/codegen/coroutines/inheritance.kt | 49 +++++++++++++++++++ .../tests/codegen/coroutines/inheritance.out | 2 + 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 kotlin-native/backend.native/tests/codegen/coroutines/inheritance.kt create mode 100644 kotlin-native/backend.native/tests/codegen/coroutines/inheritance.out diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractSuspendFunctionsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractSuspendFunctionsLowering.kt index 2f953533beb..0c0db54a20a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractSuspendFunctionsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AbstractSuspendFunctionsLowering.kt @@ -71,8 +71,14 @@ abstract class AbstractSuspendFunctionsLowering(val co declaration.acceptChildrenVoid(this) } + private fun addMissingSupertypes(clazz: IrClass) { - val suspendFunctionTypes = getAllSubstitutedSupertypes(clazz).filter { it.isSuspendFunction() }.toSet() + val suspendFunctionTypes = getAllSubstitutedSupertypes(clazz).filter { + // SuspendFunction class is some hack in old Kotlin/Native compiler versions. + // It's not used now, but is considered as SuspendFunction-like class in isSuspendFunction util, + // if found in old klib. We need just to ignore it. + it.isSuspendFunction() && it.classOrNull?.owner?.name?.toString() != "SuspendFunction" + }.toSet() for (suspendFunctionType in suspendFunctionTypes) { val suspendFunctionClassSymbol = suspendFunctionType.classOrNull ?: continue diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index ad6cbbff42a..f2cb93535b0 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -2204,6 +2204,11 @@ task coroutines_kt41394(type: KonanLocalTest) { source = "codegen/coroutines/kt41394.kt" } +task coroutines_inheritance(type: KonanLocalTest) { + useGoldenData = true + source = "codegen/coroutines/inheritance.kt" +} + standaloneTest('coroutines_suspendConversion') { useGoldenData = true source = "codegen/coroutines/suspendConversion.kt" diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/inheritance.kt b/kotlin-native/backend.native/tests/codegen/coroutines/inheritance.kt new file mode 100644 index 00000000000..df48169e28f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/inheritance.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package codegen.coroutines.inheritance + +import kotlin.test.* + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation { + companion object : EmptyContinuation() + override fun resumeWith(result: Result) { result.getOrThrow() } +} + +class SuspendHere(): suspend () -> Int { + override suspend fun invoke() : Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(42) + COROUTINE_SUSPENDED + } +} + +// in old compiler versions all suspend functions were implementing this interface +// now they are not, but let's test it works correctly +class SuspendHereLegacy(): suspend () -> Int, SuspendFunction { + override suspend fun invoke() : Int = suspendCoroutineUninterceptedOrReturn { x -> + x.resume(43) + COROUTINE_SUSPENDED + } +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +@Test fun runTest() { + var result = 0 + + builder { + result = SuspendHere()() + } + println(result) + builder { + result = SuspendHereLegacy()() + } + println(result) +} \ No newline at end of file diff --git a/kotlin-native/backend.native/tests/codegen/coroutines/inheritance.out b/kotlin-native/backend.native/tests/codegen/coroutines/inheritance.out new file mode 100644 index 00000000000..6fe5c7f6a8f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/coroutines/inheritance.out @@ -0,0 +1,2 @@ +42 +43