TIL `ContinuationInterceptor` and `CoroutineDispat...
# coroutines
z
TIL
ContinuationInterceptor
and
CoroutineDispatcher
actually have separate “polymorphic” keys. This seems to mean it’s possible to create a coroutine context with a dispatcher A and an interceptor B that wraps A, where if you ask it for the interceptor you will get B but if you ask specifically for the dispatcher you’ll get A. Has anyone written a blog or anything about gotchas with combinations of this, or done it before and hit snags? I’m seeing some weird behavior in this situation when B tries to wrap a continuation and then ask the wrapped dispatcher to intercept.
👀 1
So it seems like
advanceUntilIdle()
isn’t working with
runTest(UnconfinedTestDispatcher())
when the
ContinuationInterceptor
returns a
DispatchedContinuation
. This test fails:
Copy code
@Test
fun minimalRepro() {
    runTest(UnconfinedTestDispatcher()) {
        val parentInterceptor = coroutineContext[ContinuationInterceptor]!!
        val wrappedInterceptor =
            object : AbstractCoroutineContextElement(ContinuationInterceptor),
                ContinuationInterceptor {
                override fun <T> interceptContinuation(continuation: Continuation<T>) =
                    // Return continuation directly and the test passes
                    // (DispatchedContinuation vs Continuation).
                    parentInterceptor.interceptContinuation(continuation)
            }
        var entered = false

        withContext(wrappedInterceptor) {
            launch {
                entered = true
            }
            // OR replace this with yield() and the test passes.
            advanceUntilIdle()
            assertTrue(entered)
        }
    }
}
@Stephen Edwards @billjings can either of you explain this?