Support crossinline suspend lambda as parameter of inline function
Use fake continuation instead of ALOAD 0 while inlining Do not generate state machine for inner lambdas and inner objects, which capture crossinline suspend lambda. #KT-19159: Fixed
This commit is contained in:
+8
-1
@@ -35,7 +35,11 @@ fun builderConsumer(c: suspend () -> Consumer): Consumer {
|
||||
}
|
||||
|
||||
class Container {
|
||||
var y: String = "FAIL 1"
|
||||
var y: String = "FAIL 0"
|
||||
|
||||
val consumer0 = crossInlineBuilderConsumer { s ->
|
||||
y = s
|
||||
}
|
||||
|
||||
val consumer1 = crossInlineBuilderConsumer { s ->
|
||||
builder {
|
||||
@@ -108,6 +112,9 @@ class Container {
|
||||
|
||||
fun box(): String {
|
||||
val c = Container()
|
||||
c.consumer0.consume("OK")
|
||||
if (c.y != "OK") return c.y
|
||||
c.y = "FAIL 1"
|
||||
c.consumer1.consume("OK")
|
||||
if (c.y != "OK") return c.y
|
||||
c.y = "FAIL 2"
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend inline fun test1(c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
val a = 1
|
||||
test2 {
|
||||
val b = 2
|
||||
test1 {
|
||||
val c = a + b // 3
|
||||
run {
|
||||
val a = c + 1 // 4
|
||||
test1 {
|
||||
val b = c + c // 6
|
||||
test2 {
|
||||
val c = b - a // 2
|
||||
res = "${calculate()} $a$b$c"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK 462") return res
|
||||
return "OK"
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
inline suspend fun foo(crossinline a: suspend () -> Unit, crossinline b: suspend () -> Unit) {
|
||||
var x = "OK"
|
||||
bar { x; a(); b() }
|
||||
}
|
||||
|
||||
inline suspend fun bar(crossinline l: suspend () -> Unit) {
|
||||
val c : suspend () -> Unit = { l() }
|
||||
c()
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
fun box(): String {
|
||||
var y = "fail"
|
||||
builder {
|
||||
foo({ y = "O" }) { y += "K" }
|
||||
}
|
||||
return y
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
}
|
||||
|
||||
val defaultController = Controller()
|
||||
|
||||
suspend inline fun test1(controller: Controller = defaultController, crossinline c: suspend Controller.() -> Unit) {
|
||||
controller.c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(controller: Controller = defaultController, crossinline c: suspend Controller.() -> Unit) {
|
||||
val l : suspend () -> Unit = {
|
||||
controller.c()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test3(controller: Controller = defaultController, crossinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
controller.c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
builder {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
defaultController.res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
defaultController.res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
val controller = Controller()
|
||||
controller.res = "FAIL 4"
|
||||
builder {
|
||||
test1(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
builder {
|
||||
test2(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
builder {
|
||||
test3(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
}
|
||||
|
||||
val defaultController = Controller()
|
||||
|
||||
suspend inline fun test(controller: Controller = defaultController, c: suspend Controller.() -> Unit) {
|
||||
controller.c()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
builder {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
val controller = Controller()
|
||||
controller.res = "FAIL 2"
|
||||
builder {
|
||||
test(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test1(crossinline runner: suspend () -> Unit) {
|
||||
val l : suspend () -> Unit = { runner() }
|
||||
builder { l() }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
inline fun test2(crossinline c: suspend () -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder { sr.run() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Start coroutine call is possible
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test1(noinline c: suspend () -> Unit) {
|
||||
val l : suspend () -> Unit = { c() }
|
||||
builder { l() }
|
||||
}
|
||||
|
||||
val EmptyContinuation = object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
inline fun test2(noinline c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
inline fun test3(noinline c: suspend () -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder { sr.run() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 6"
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 7"
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun test1(c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: suspend() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test4(crossinline c: suspend() -> Unit) {
|
||||
val l : suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test5(crossinline c: suspend() -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.experimental.jvm.internal.*
|
||||
|
||||
object EmptyContinuation: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
var continuationChanged = true
|
||||
var savedContinuation: Continuation<Unit>? = null
|
||||
|
||||
suspend inline fun saveContinuation() = suspendCoroutineUninterceptedOrReturn<Unit> { c ->
|
||||
savedContinuation = c
|
||||
Unit
|
||||
}
|
||||
|
||||
suspend inline fun checkContinuation(continuation: Continuation<Unit>) = suspendCoroutineUninterceptedOrReturn<Unit> { c ->
|
||||
continuationChanged = (continuation !== c)
|
||||
Unit
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
builder {
|
||||
saveContinuation()
|
||||
test1 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (continuationChanged) return "FAIL 1"
|
||||
continuationChanged = true
|
||||
builder {
|
||||
saveContinuation()
|
||||
test2 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (continuationChanged) return "FAIL 2"
|
||||
continuationChanged = true
|
||||
builder {
|
||||
saveContinuation()
|
||||
test3 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (continuationChanged) return "FAIL 3"
|
||||
continuationChanged = false
|
||||
builder {
|
||||
saveContinuation()
|
||||
test4 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (!continuationChanged) return "FAIL 4"
|
||||
continuationChanged = false
|
||||
builder {
|
||||
saveContinuation()
|
||||
test5 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (!continuationChanged) return "FAIL 5"
|
||||
return "OK"
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
suspend inline fun test1(crossinline c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: () -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: () -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend () -> Unit) {
|
||||
builder { c() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
suspend inline fun test1(crossinline c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: suspend () -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 7"
|
||||
builder {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
suspend inline fun test1(noinline c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: () -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: () -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend () -> Unit) {
|
||||
builder { c() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
// Start coroutine call is possible
|
||||
// Block is allowed to be called directly inside inline function
|
||||
|
||||
suspend inline fun test1(noinline c: suspend () -> Unit) {
|
||||
val l : suspend () -> Unit = { c() }
|
||||
builder { l() }
|
||||
}
|
||||
|
||||
object EmptyContinuation: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test4(noinline c: suspend () -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test4 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 7"
|
||||
builder {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 8"
|
||||
builder {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 9"
|
||||
builder {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test4 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
suspend inline fun test(c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend () -> Unit) {
|
||||
builder { c() }
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
builder {
|
||||
test {
|
||||
transform {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
suspend inline fun test(c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
object Result {
|
||||
var a: String = ""
|
||||
var b: Int = 0
|
||||
}
|
||||
|
||||
suspend inline fun inlineMe(c: suspend () -> Unit) {
|
||||
var a = ""
|
||||
var b = 0
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
b++
|
||||
a += "a"
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
c()
|
||||
r.run()
|
||||
Result.a = a
|
||||
Result.b = b
|
||||
}
|
||||
suspend inline fun noinlineMe(noinline c: suspend () -> Unit) {
|
||||
var a = ""
|
||||
var b = 0
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
b += 2
|
||||
a += "b"
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
c()
|
||||
r.run()
|
||||
Result.a += a
|
||||
Result.b += b
|
||||
}
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
var a = ""
|
||||
var b = 0
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
b += 3
|
||||
a += "c"
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
c()
|
||||
r.run()
|
||||
Result.a += a
|
||||
Result.b += b
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun dummy() {
|
||||
val local0 = 0
|
||||
val local1 = 0
|
||||
val local2 = 0
|
||||
val local3 = 0
|
||||
val local4 = 0
|
||||
val local5 = 0
|
||||
val local6 = 0
|
||||
val local7 = 0
|
||||
val local8 = 0
|
||||
val local9 = 0
|
||||
val local10 = 0
|
||||
val local11 = 0
|
||||
val local12 = 0
|
||||
val local13 = 0
|
||||
val local14 = 0
|
||||
val local15 = 0
|
||||
val local16 = 0
|
||||
val local17 = 0
|
||||
val local18 = 0
|
||||
val local19 = 0
|
||||
val local20 = 0
|
||||
val local21 = 0
|
||||
val local22 = 0
|
||||
}
|
||||
|
||||
suspend fun inlineSite() {
|
||||
inlineMe {
|
||||
dummy()
|
||||
dummy()
|
||||
}
|
||||
if (Result.a != "aa" || Result.b != 2) throw RuntimeException("FAIL 1")
|
||||
noinlineMe {
|
||||
dummy()
|
||||
dummy()
|
||||
}
|
||||
if (Result.a != "aabb" || Result.b != 6) throw RuntimeException("FAIL 2")
|
||||
crossinlineMe {
|
||||
dummy()
|
||||
dummy()
|
||||
}
|
||||
if (Result.a != "aabbcc" || Result.b != 12) throw RuntimeException("FAIL 3")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
inlineSite()
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun inlineMe(c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
}
|
||||
suspend inline fun noinlineMe(noinline c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
}
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var k = 0;
|
||||
|
||||
suspend fun calculateI() {
|
||||
i++
|
||||
}
|
||||
|
||||
suspend fun calculateJ() {
|
||||
j++
|
||||
}
|
||||
|
||||
suspend fun calculateK() {
|
||||
k++
|
||||
}
|
||||
|
||||
suspend fun inlineSite() {
|
||||
inlineMe {
|
||||
calculateI()
|
||||
calculateI()
|
||||
}
|
||||
noinlineMe {
|
||||
calculateJ()
|
||||
calculateJ()
|
||||
}
|
||||
crossinlineMe {
|
||||
calculateK()
|
||||
calculateK()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
inlineSite()
|
||||
}
|
||||
if (i != 10) return "FAIL I"
|
||||
if (j != 10) return "FAIL J"
|
||||
if (k != 10) return "FAIL K"
|
||||
return "OK"
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
inline fun test1(crossinline runner: suspend Controller.() -> Unit) {
|
||||
val l : suspend Controller.() -> Unit = { runner() }
|
||||
builder(this) { l() }
|
||||
}
|
||||
|
||||
inline fun test2(crossinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder(this) { sr.run() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
val controller = Controller()
|
||||
controller.test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
controller.test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
controller.test2 {
|
||||
res = calculate()
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
controller.test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
controller.test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Start coroutine call is possible
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
val EmptyContinuation = object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
inline fun test1(noinline c: suspend Controller.() -> Unit) {
|
||||
val l : suspend Controller.() -> Unit = { c() }
|
||||
builder(this) { l() }
|
||||
}
|
||||
|
||||
inline fun test2(noinline c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(this, EmptyContinuation)
|
||||
}
|
||||
|
||||
inline fun test3(noinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder(this) { sr.run() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, EmptyContinuation)
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
val controller = Controller()
|
||||
controller.test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
controller.test2 {
|
||||
res = "OK"
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
controller.test3 {
|
||||
res = "OK"
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
controller.test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
controller.test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
controller.test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 7"
|
||||
controller.test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(crossinline c: Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: Controller.() -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: Controller.() -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend Controller.() -> Unit) {
|
||||
builder(this) { c() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller : Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(crossinline c: suspend Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: suspend Controller.() -> Unit) {
|
||||
val l: suspend Controller.() -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 7"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(noinline c: Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: Controller.() -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: Controller.() -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend Controller.() -> Unit) {
|
||||
builder(this) { c() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
// Start coroutine call is possible
|
||||
// Block is allowed to be called directly inside inline function
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
object EmptyContinuation: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(noinline c: suspend Controller.() -> Unit) {
|
||||
val l : suspend Controller.() -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(this, EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: suspend Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test4(noinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, EmptyContinuation)
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test4 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 7"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 8"
|
||||
builder(controller) {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 9"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test4 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test(c: Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend Controller.() -> Unit) {
|
||||
builder(this) { c() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
builder(controller) {
|
||||
test {
|
||||
transform {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test(c: suspend Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL"
|
||||
return "OK"
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
val l1 : suspend () -> Unit = {
|
||||
c()
|
||||
}
|
||||
l1()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "OK"
|
||||
builder {
|
||||
crossinlineMe {
|
||||
res = "FAIL 1"
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL 2"
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
c()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
o.run()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val o1 = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
o1.run()
|
||||
}
|
||||
}
|
||||
o.run()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run1()
|
||||
suspend fun run2()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run1() {
|
||||
c1()
|
||||
}
|
||||
override suspend fun run2() {
|
||||
c2()
|
||||
}
|
||||
}
|
||||
o.run1()
|
||||
o.run2()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
|
||||
suspend fun incrementI() {
|
||||
i++
|
||||
}
|
||||
|
||||
suspend fun incrementJ() {
|
||||
j++
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe({ incrementI() }) { incrementJ() }
|
||||
}
|
||||
if (i != 1) return "FAIL i $i"
|
||||
if (j != 1) return "FAIL i $i"
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
o.run()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "OK"
|
||||
builder {
|
||||
crossinlineMe {
|
||||
res = "FAIL 1"
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL 2"
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL"
|
||||
return "OK"
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe2(crossinline c: suspend () -> Unit) {
|
||||
crossinlineMe { c(); c() }
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
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) }
|
||||
}
|
||||
|
||||
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 {
|
||||
crossinlineMe2 {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
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,84 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun inlineMe(c: suspend (String) -> String, d: suspend () -> String): String {
|
||||
return c(try { d() } catch (e: Exception) { "Exception 1 ${e.message}" })
|
||||
}
|
||||
|
||||
suspend inline fun noinlineMe(noinline c: suspend (String) -> String, noinline d: suspend () -> String): String {
|
||||
return c(try { d() } catch (e: Exception) { "Exception 1 ${e.message}" })
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend (String) -> String, crossinline d: suspend () -> String): String {
|
||||
return c(try { d() } catch (e: Exception) { "Exception 1 ${e.message}" })
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun yieldString(s: String) = s
|
||||
|
||||
suspend fun throwException(s: String): String {
|
||||
throw RuntimeException(s)
|
||||
}
|
||||
|
||||
suspend fun inlineSite() {
|
||||
var res = inlineMe({ it }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 1: $res")
|
||||
|
||||
res = inlineMe({ it }) { throwException("OK") }
|
||||
if (res != "Exception 1 OK") throw RuntimeException("FAIL 2: $res")
|
||||
|
||||
res = noinlineMe({ it }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 3: $res")
|
||||
|
||||
res = noinlineMe({ it }) { throwException("OK") }
|
||||
if (res != "Exception 1 OK") throw RuntimeException("FAIL 4: $res")
|
||||
|
||||
res = crossinlineMe({ it }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 5: $res")
|
||||
|
||||
res = crossinlineMe({ it }) { throwException("OK") }
|
||||
if (res != "Exception 1 OK") throw RuntimeException("FAIL 6: $res")
|
||||
|
||||
res = inlineMe({ try {yieldString(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 7: $res")
|
||||
|
||||
res = inlineMe({ try {throwException(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "Exception 2 OK") throw RuntimeException("FAIL 8: $res")
|
||||
|
||||
res = noinlineMe({ try {yieldString(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 9: $res")
|
||||
|
||||
res = noinlineMe({ try {throwException(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "Exception 2 OK") throw RuntimeException("FAIL 10: $res")
|
||||
|
||||
res = crossinlineMe({ try {yieldString(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 11: $res")
|
||||
|
||||
res = crossinlineMe({ try {throwException(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "Exception 2 OK") throw RuntimeException("FAIL 12: $res")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
inlineSite()
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user