Wrap continuation with ContinuationImpl on callable references

in startCoroutineUninterceptedOrReturn. Otherwise, the coroutine will
not be interceptable later.

Add a test, which checks, that intercepted continuation is released.

 #KT-55869
This commit is contained in:
Ilmir Usmanov
2023-01-17 05:48:12 +01:00
committed by Space Team
parent 9a2cb2609f
commit d18672bfb1
23 changed files with 413 additions and 39 deletions
@@ -24,7 +24,9 @@ import kotlin.wasm.internal.*
@kotlin.internal.InlineOnly
public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
completion: Continuation<T>
): Any? = startCoroutineUninterceptedOrReturnIntrinsic0(this, completion)
): Any? = startCoroutineUninterceptedOrReturnIntrinsic0(
this, if (this !is CoroutineImpl) createSimpleCoroutineFromSuspendFunction(completion) else completion
)
/**
* Starts an unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
@@ -43,7 +45,9 @@ public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrRetu
public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
receiver: R,
completion: Continuation<T>
): Any? = startCoroutineUninterceptedOrReturnIntrinsic1(this, receiver, completion)
): Any? = startCoroutineUninterceptedOrReturnIntrinsic1(
this, receiver, if (this !is CoroutineImpl) createSimpleCoroutineFromSuspendFunction(completion) else completion
)
@Suppress("UNCHECKED_CAST")
@kotlin.internal.InlineOnly
@@ -51,7 +55,9 @@ internal actual inline fun <R, P, T> (suspend R.(P) -> T).startCoroutineUninterc
receiver: R,
param: P,
completion: Continuation<T>
): Any? = startCoroutineUninterceptedOrReturnIntrinsic2(this, receiver, param, completion)
): Any? = startCoroutineUninterceptedOrReturnIntrinsic2(
this, receiver, param, if (this !is CoroutineImpl) createSimpleCoroutineFromSuspendFunction(completion) else completion
)
/**
* Creates unintercepted coroutine without receiver and with result type [T].
@@ -137,4 +143,14 @@ private inline fun <T> createCoroutineFromSuspendFunction(
return block()
}
}
}
}
@PublishedApi
internal fun <T> createSimpleCoroutineFromSuspendFunction(
completion: Continuation<T>
): CoroutineImpl = object : CoroutineImpl(completion as Continuation<Any?>) {
override fun doResume(): Any? {
if (exception != null) throw exception as Throwable
return result
}
}