[K/N] Wrap continuation with ContinuationImpl on callable references
#KT-55869
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND: JS_IR, JS_IR_ES6, NATIVE
|
// IGNORE_BACKEND: JS_IR, JS_IR_ES6
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
import kotlin.coroutines.intrinsics.*
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
// IGNORE_BACKEND: JS_IR, JS_IR_ES6, NATIVE
|
// IGNORE_BACKEND: JS_IR, JS_IR_ES6
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
import kotlin.coroutines.intrinsics.*
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// IGNORE_BACKEND: NATIVE
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
import kotlin.coroutines.intrinsics.*
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|||||||
+49
-10
@@ -27,10 +27,13 @@ public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrRetu
|
|||||||
completion: Continuation<T>
|
completion: Continuation<T>
|
||||||
): Any? {
|
): Any? {
|
||||||
val function = this as? Function1<Continuation<T>, Any?>
|
val function = this as? Function1<Continuation<T>, Any?>
|
||||||
return if (function != null)
|
return if (function == null)
|
||||||
function.invoke(completion)
|
|
||||||
else
|
|
||||||
startCoroutineUninterceptedOrReturnFallback(this, completion)
|
startCoroutineUninterceptedOrReturnFallback(this, completion)
|
||||||
|
else {
|
||||||
|
function.invoke(
|
||||||
|
completion.takeIf { this is BaseContinuationImpl } ?: wrapWithContinuationImpl(completion)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -64,10 +67,13 @@ public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedO
|
|||||||
completion: Continuation<T>
|
completion: Continuation<T>
|
||||||
): Any? {
|
): Any? {
|
||||||
val function = this as? Function2<R, Continuation<T>, Any?>
|
val function = this as? Function2<R, Continuation<T>, Any?>
|
||||||
return if (function != null)
|
return if (function == null)
|
||||||
function.invoke(receiver, completion)
|
|
||||||
else
|
|
||||||
startCoroutineUninterceptedOrReturnFallback(this, receiver, completion)
|
startCoroutineUninterceptedOrReturnFallback(this, receiver, completion)
|
||||||
|
else {
|
||||||
|
function.invoke(receiver,
|
||||||
|
completion.takeIf { this is BaseContinuationImpl } ?: wrapWithContinuationImpl(completion)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -91,10 +97,13 @@ internal actual inline fun <R, P, T> (suspend R.(P) -> T).startCoroutineUninterc
|
|||||||
completion: Continuation<T>
|
completion: Continuation<T>
|
||||||
): Any? {
|
): Any? {
|
||||||
val function = this as? Function3<R, P, Continuation<T>, Any?>
|
val function = this as? Function3<R, P, Continuation<T>, Any?>
|
||||||
return if (function != null)
|
return if (function == null)
|
||||||
function.invoke(receiver, param, completion)
|
|
||||||
else
|
|
||||||
startCoroutineUninterceptedOrReturnFallback(this, receiver, param, completion)
|
startCoroutineUninterceptedOrReturnFallback(this, receiver, param, completion)
|
||||||
|
else {
|
||||||
|
function.invoke(receiver, param,
|
||||||
|
completion.takeIf { this is BaseContinuationImpl } ?: wrapWithContinuationImpl(completion)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -288,4 +297,34 @@ internal inline fun createContinuationArgumentFromCallback(
|
|||||||
|
|
||||||
return Unit // Not suspended.
|
return Unit // Not suspended.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal fun <T> wrapWithContinuationImpl(completion: Continuation<T>) =
|
||||||
|
createSimpleCoroutineForSuspendFunction(probeCoroutineCreated(completion))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is used when [startCoroutineUninterceptedOrReturn] encounters suspending lambda that does not extend BaseContinuationImpl.
|
||||||
|
*
|
||||||
|
* It happens in two cases: callable reference to suspending function or tail-call lambdas.
|
||||||
|
*
|
||||||
|
* This function is the same as above, but does not run lambda itself - the caller is expected to call [invoke] manually.
|
||||||
|
*/
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private fun <T> createSimpleCoroutineForSuspendFunction(
|
||||||
|
completion: Continuation<T>
|
||||||
|
): Continuation<T> {
|
||||||
|
val context = completion.context
|
||||||
|
return if (context === EmptyCoroutineContext)
|
||||||
|
object : RestrictedContinuationImpl(completion as Continuation<Any?>) {
|
||||||
|
override fun invokeSuspend(result: Result<Any?>): Any? {
|
||||||
|
return result.getOrThrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
object : ContinuationImpl(completion as Continuation<Any?>, context) {
|
||||||
|
override fun invokeSuspend(result: Result<Any?>): Any? {
|
||||||
|
return result.getOrThrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user