Support open suspend members and super-calls

The problem was that the resume call (from doResume) for open members
was based on common INVOKEVIRTUAL to the original function
that lead to the invocation of the override when it was expected
to be the overridden (after super-call being suspended)

The solution is to generate method bodies for open members into
the special $suspendImpl synthetic function that may be called
from the doResume implementation

 #KT-17587 Fixed
This commit is contained in:
Denis Zharkov
2017-05-15 10:43:31 +03:00
parent e75b6c8404
commit d24d3a73d7
10 changed files with 185 additions and 2 deletions
@@ -0,0 +1,34 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
open class A(val v: String) {
suspend fun suspendThere(v: String): String = suspendCoroutineOrReturn { x ->
x.resume(v)
COROUTINE_SUSPENDED
}
open suspend fun suspendHere(): String = suspendThere("O") + suspendThere(v)
}
class B(v: String) : A(v) {
override suspend fun suspendHere(): String = super.suspendHere() + suspendThere("56")
}
fun builder(c: suspend A.() -> Unit) {
c.startCoroutine(B("K"), EmptyContinuation)
}
fun box(): String {
var result = ""
builder {
result = suspendHere()
}
if (result != "OK56") return "fail 1: $result"
return "OK"
}
@@ -0,0 +1,38 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
interface A {
val v: String
suspend fun suspendThere(v: String): String = suspendCoroutineOrReturn { x ->
x.resume(v)
COROUTINE_SUSPENDED
}
suspend fun suspendHere(): String = suspendThere("O") + suspendThere(v)
}
interface A2 : A {
override suspend fun suspendHere(): String = super.suspendHere() + suspendThere("56")
}
class B(override val v: String) : A2
fun builder(c: suspend A.() -> Unit) {
c.startCoroutine(B("K"), EmptyContinuation)
}
fun box(): String {
var result = ""
builder {
result = suspendHere()
}
if (result != "OK56") return "fail 1: $result"
return "OK"
}