Narrow down return type of tryResumeSend/Receive
They return Symbol?
diff --git a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt
index 9f672af..ce0acc0 100644
--- a/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt
+++ b/kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt
@@ -450,8 +450,8 @@
@JvmField val select: SelectInstance<R>,
@JvmField val block: suspend (SendChannel<E>) -> R
) : Send(), DisposableHandle {
- override fun tryResumeSend(otherOp: PrepareOp?): Any? =
- select.trySelectOther(otherOp)
+ override fun tryResumeSend(otherOp: PrepareOp?): Symbol? =
+ select.trySelectOther(otherOp) as Symbol? // must return symbol
override fun completeResumeSend() {
block.startCoroutine(receiver = channel, completion = select.completion)
@@ -473,7 +473,7 @@
@JvmField val element: E
) : Send() {
override val pollResult: Any? get() = element
- override fun tryResumeSend(otherOp: PrepareOp?): Any? = RESUME_TOKEN.also { otherOp?.finishPrepare() }
+ override fun tryResumeSend(otherOp: PrepareOp?): Symbol? = RESUME_TOKEN.also { otherOp?.finishPrepare() }
override fun completeResumeSend() {}
override fun resumeSendClosed(closed: Closed<*>) {}
}
@@ -898,9 +898,11 @@
}
@Suppress("IMPLICIT_CAST_TO_ANY")
- override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Any? {
+ override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Symbol? {
otherOp?.finishPrepare()
- return cont.tryResume(resumeValue(value), otherOp?.desc)
+ val token = cont.tryResume(resumeValue(value), otherOp?.desc) ?: return null
+ assert { token === RESUME_TOKEN } // the only other possible result
+ return RESUME_TOKEN
}
override fun completeResumeReceive(value: E) = cont.completeResume(RESUME_TOKEN)
@@ -919,9 +921,11 @@
@JvmField val iterator: Itr<E>,
@JvmField val cont: CancellableContinuation<Boolean>
) : Receive<E>() {
- override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Any? {
+ override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Symbol? {
otherOp?.finishPrepare()
- return cont.tryResume(true, otherOp?.desc)
+ val token = cont.tryResume(true, otherOp?.desc) ?: return null
+ assert { token === RESUME_TOKEN } // the only other possible result
+ return RESUME_TOKEN
}
override fun completeResumeReceive(value: E) {
@@ -953,8 +957,8 @@
@JvmField val block: suspend (Any?) -> R,
@JvmField val receiveMode: Int
) : Receive<E>(), DisposableHandle {
- override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Any? =
- select.trySelectOther(otherOp)
+ override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Symbol? =
+ select.trySelectOther(otherOp) as Symbol?
@Suppress("UNCHECKED_CAST")
override fun completeResumeReceive(value: E) {
@@ -1019,7 +1023,7 @@
// RETRY_ATOMIC for retry (only when otherOp != null),
// RESUME_TOKEN on success (call completeResumeSend)
// Must call otherOp?.finishPrepare() before deciding on result other than RETRY_ATOMIC
- abstract fun tryResumeSend(otherOp: PrepareOp?): Any?
+ abstract fun tryResumeSend(otherOp: PrepareOp?): Symbol?
abstract fun completeResumeSend()
abstract fun resumeSendClosed(closed: Closed<*>)
}
@@ -1033,7 +1037,7 @@
// RETRY_ATOMIC for retry (only when otherOp != null),
// RESUME_TOKEN on success (call completeResumeReceive)
// Must call otherOp?.finishPrepare() before deciding on result other than RETRY_ATOMIC
- fun tryResumeReceive(value: E, otherOp: PrepareOp?): Any?
+ fun tryResumeReceive(value: E, otherOp: PrepareOp?): Symbol?
fun completeResumeReceive(value: E)
}
@@ -1045,9 +1049,11 @@
override val pollResult: Any?,
@JvmField val cont: CancellableContinuation<Unit>
) : Send() {
- override fun tryResumeSend(otherOp: PrepareOp?): Any? {
+ override fun tryResumeSend(otherOp: PrepareOp?): Symbol? {
otherOp?.finishPrepare()
- return cont.tryResume(Unit, otherOp?.desc)
+ val token = cont.tryResume(Unit, otherOp?.desc)
+ assert { token === RESUME_TOKEN } // the only other possible result
+ return RESUME_TOKEN
}
override fun completeResumeSend() = cont.completeResume(RESUME_TOKEN)
override fun resumeSendClosed(closed: Closed<*>) = cont.resumeWithException(closed.sendException)
@@ -1065,9 +1071,9 @@
override val offerResult get() = this
override val pollResult get() = this
- override fun tryResumeSend(otherOp: PrepareOp?): Any? = RESUME_TOKEN.also { otherOp?.finishPrepare() }
+ override fun tryResumeSend(otherOp: PrepareOp?): Symbol? = RESUME_TOKEN.also { otherOp?.finishPrepare() }
override fun completeResumeSend() {}
- override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Any? = RESUME_TOKEN.also { otherOp?.finishPrepare() }
+ override fun tryResumeReceive(value: E, otherOp: PrepareOp?): Symbol? = RESUME_TOKEN.also { otherOp?.finishPrepare() }
override fun completeResumeReceive(value: E) {}
override fun resumeSendClosed(closed: Closed<*>) = assert { false } // "Should be never invoked"
override fun toString(): String = "Closed[$closeCause]"
diff --git a/kotlinx-coroutines-core/common/src/selects/Select.kt b/kotlinx-coroutines-core/common/src/selects/Select.kt
index 550ea1f..372c9e3 100644
--- a/kotlinx-coroutines-core/common/src/selects/Select.kt
+++ b/kotlinx-coroutines-core/common/src/selects/Select.kt
@@ -93,7 +93,7 @@
*
* @suppress **This is unstable API and it is subject to change.**
*/
-@InternalCoroutinesApi
+@InternalCoroutinesApi // todo: sealed interface https://youtrack.jetbrains.com/issue/KT-22286
public interface SelectInstance<in R> {
/**
* Returns `true` when this [select] statement had already picked a clause to execute.
@@ -112,6 +112,10 @@
* * `null` on failure to select (already selected).
* [otherOp] is not null when trying to rendezvous with this select from inside of another select.
* In this case, [PrepareOp.finishPrepare] must be called before deciding on any value other than [RETRY_ATOMIC].
+ *
+ * Note, that this method's actual return type is `Symbol?` but we cannot declare it as such, because this
+ * member is public, but [Symbol] is internal. When [SelectInstance] becomes a `sealed interface`
+ * (see KT-222860) we can declare this method as internal.
*/
public fun trySelectOther(otherOp: PrepareOp?): Any?