Implement coroutineContext intrinsic
This intrinsic allows coroutine to access its context without suspention and, furthermore, disabling tail-call optimization. KT-17609: Fixed
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
suspend fun suspendHere() = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK"
|
||||
|
||||
suspend fun multipleArgs(a: Any, b: Any, c: Any) = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK"
|
||||
|
||||
fun builder(c: suspend () -> String): String {
|
||||
var fromSuspension: String? = null
|
||||
|
||||
val continuation = object: Continuation<String> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
fromSuspension = "Exception: ${exception}"
|
||||
}
|
||||
|
||||
override fun resume(value: String) {
|
||||
fromSuspension = value
|
||||
}
|
||||
}
|
||||
|
||||
c.startCoroutine(continuation)
|
||||
|
||||
return fromSuspension as String
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = builder { suspendHere() }
|
||||
if (res != "OK") { return "fail 1 $res"}
|
||||
res = builder { multipleArgs(1,1,1) }
|
||||
if (res != "OK") { return "fail 2 $res"}
|
||||
res = builder { if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" }
|
||||
if (res != "OK") { return "fail 3 $res"}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class Controller {
|
||||
suspend fun controllerSuspendHere() = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK"
|
||||
|
||||
suspend fun controllerMultipleArgs(a: Any, b: Any, c: Any) = if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK"
|
||||
|
||||
fun builder(c: suspend Controller.() -> String): String {
|
||||
var fromSuspension: String? = null
|
||||
|
||||
c.startCoroutine(this, object: Continuation<String> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
fromSuspension = "Exception: " + exception.message!!
|
||||
}
|
||||
|
||||
override fun resume(value: String) {
|
||||
fromSuspension = value
|
||||
}
|
||||
})
|
||||
|
||||
return fromSuspension as String
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val c = Controller()
|
||||
var res = c.builder { controllerSuspendHere() }
|
||||
if (res != "OK") { return "fail 1 $res"}
|
||||
res = c.builder { controllerMultipleArgs(1,1,1) }
|
||||
if (res != "OK") { return "fail 2 $res"}
|
||||
res = c.builder { if(coroutineContext != EmptyCoroutineContext) "$coroutineContext != $EmptyCoroutineContext" else "OK" }
|
||||
if (res != "OK") { return "fail 3 $res"}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+59
@@ -0,0 +1,59 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
import helpers.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class Controller {
|
||||
val coroutineContext = object : CoroutineContext {
|
||||
public override fun <E : CoroutineContext.Element> get(key: CoroutineContext.Key<E>): E? = null
|
||||
public override fun <R> fold(initial: R, operation: (R, CoroutineContext.Element) -> R): R = initial
|
||||
public override fun plus(context: CoroutineContext): CoroutineContext = context
|
||||
public override fun minusKey(key: CoroutineContext.Key<*>): CoroutineContext = this
|
||||
public override fun hashCode(): Int = 0
|
||||
public override fun toString(): String = "AnotherEmptyCoroutineContext"
|
||||
}
|
||||
|
||||
suspend fun controllerSuspendHere() = if(coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK"
|
||||
|
||||
suspend fun controllerSuspendHereIntrinsic() = if(kotlin.coroutines.experimental.intrinsics.coroutineContext != EmptyCoroutineContext)
|
||||
"${kotlin.coroutines.experimental.intrinsics.coroutineContext} != $EmptyCoroutineContext"
|
||||
else
|
||||
"OK"
|
||||
|
||||
suspend fun controllerMultipleArgs(a: Any, b: Any, c: Any) = if(coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK"
|
||||
|
||||
fun builder(c: suspend Controller.() -> String): String {
|
||||
var fromSuspension: String? = null
|
||||
|
||||
c.startCoroutine(this, object: Continuation<String> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
fromSuspension = "Exception: " + exception.message!!
|
||||
}
|
||||
|
||||
override fun resume(value: String) {
|
||||
fromSuspension = value
|
||||
}
|
||||
})
|
||||
|
||||
return fromSuspension as String
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val v = Controller()
|
||||
var res = v.builder { controllerMultipleArgs(1,1,1) }
|
||||
if (res != "OK") { return "fail 1 $res"}
|
||||
res = v.builder { if(coroutineContext == EmptyCoroutineContext) "$coroutineContext == $EmptyCoroutineContext" else "OK" }
|
||||
if (res != "OK") { return "fail 2 $res"}
|
||||
res = v.builder { controllerSuspendHereIntrinsic() }
|
||||
if (res != "OK") { return "fail 3 $res"}
|
||||
res = v.builder { controllerSuspendHere() }
|
||||
if (res != "OK") { return "fail 4 $res"}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user