Support local suspend functions

Treat them like lambdas. This means:
1) Like local suspend lambdas, which become "non-suspend" after creating
jvmSuspendView, they do this as well
2) They both are generated with the same codegen.
3) They are treated differently only on front-end side.
 #KT-20364: Fixed
This commit is contained in:
Ilmir Usmanov
2018-04-02 21:50:56 +03:00
parent 5a752da9e9
commit bd0ad26dcf
29 changed files with 797 additions and 29 deletions
@@ -0,0 +1,23 @@
// IGNORE_BACKEND_WITHOUT_CHECK: JVM, JS, NATIVE
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
suspend fun callLocal(): String {
val local = suspend fun() = "OK"
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(a: String, b: String): String {
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume(a + b)
COROUTINE_SUSPENDED
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal("O", "K")
}
return res
}
@@ -0,0 +1,28 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
val a = "O"
val b = "K"
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume(a + b)
COROUTINE_SUSPENDED
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend fun String.local() = suspendCoroutineOrReturn<String> {
it.resume(this)
COROUTINE_SUSPENDED
}
return "OK".local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend infix fun String.local(a: String) = suspendCoroutineOrReturn<String> {
it.resume(this + a)
COROUTINE_SUSPENDED
}
return "O" local "K"
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,29 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
val l: suspend () -> String = {
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume("OK")
COROUTINE_SUSPENDED
}
local()
}
return l()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,37 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend fun local(): String {
suspend fun local(): String {
suspend fun local(): String {
suspend fun local(): String {
suspend fun local(): String {
return "OK"
}
return local()
}
return local()
}
return local()
}
return local()
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,22 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
suspend fun callLocal(): String {
suspend fun local() = "OK"
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(): String {
suspend fun local() = suspendCoroutineOrReturn<String> {
it.resume("OK")
COROUTINE_SUSPENDED
}
return local()
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal()
}
return res
}
@@ -0,0 +1,63 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
var result = "FAIL"
var i = 0
var finished = false
var proceed: () -> Unit = {}
suspend fun suspendHere() = suspendCoroutine<Unit> {c ->
i++
proceed = { c.resume(Unit) }
}
suspend fun callLocal() {
suspend fun local() {
suspendHere()
suspendHere()
suspendHere()
suspendHere()
suspendHere()
}
local()
local()
}
fun builder(c: suspend () -> Unit) {
val continuation = object: Continuation<Unit> {
override val context: CoroutineContext
get() = EmptyCoroutineContext
override fun resume(value: Unit) {
proceed = {
result = "OK"
finished = true
}
}
override fun resumeWithException(exception: Throwable) {
throw exception
}
}
c.startCoroutine(continuation)
}
fun box(): String {
builder {
callLocal()
}
for (counter in 0 until 10) {
if (i != counter + 1) return "Expected ${counter + 1}, got $i"
proceed()
}
if (i != 10) return "FAIL $i"
if (finished) return "resume on root continuation is called"
proceed()
if (!finished) return "resume on root continuation is not called"
return result
}
@@ -0,0 +1,26 @@
// WITH_RUNTIME
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.experimental.*
import kotlin.coroutines.experimental.intrinsics.*
suspend fun callLocal(a: String, b: String): String {
suspend fun local(a: String, b: String) = suspendCoroutineOrReturn<String> {
it.resume(a + b)
COROUTINE_SUSPENDED
}
return local(a, b)
}
fun builder(c: suspend () -> Unit) {
c.startCoroutine(EmptyContinuation)
}
fun box(): String {
var res = "FAIL"
builder {
res = callLocal("O", "K")
}
return res
}