Skip to content

Commit

Permalink
Fix #2764 & #2760 (#2765)
Browse files Browse the repository at this point in the history
  • Loading branch information
nomisRev committed Jul 16, 2022
1 parent feb3c44 commit 6c0fc8c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
Expand Up @@ -568,7 +568,7 @@ import kotlin.coroutines.resume
* ```
* <!--- KNIT example-effect-guide-13.kt -->
*/
public interface Effect<out R, out A> {
public sealed interface Effect<out R, out A> {
/**
* Runs the suspending computation by creating a [Continuation], and running the `fold` function
* over the computation.
Expand Down Expand Up @@ -704,6 +704,10 @@ internal class Token {
* the result.
*/
@PublishedApi
@Deprecated(
"This will become private in Arrow 2.0, and is not going to be visible from binary anymore",
level = DeprecationLevel.WARNING
)
internal class FoldContinuation<B>(
private val token: Token,
override val context: CoroutineContext,
Expand Down Expand Up @@ -754,7 +758,11 @@ internal class FoldContinuation<B>(
*/
public fun <R, A> effect(f: suspend EffectScope<R>.() -> A): Effect<R, A> = DefaultEffect(f)

private class DefaultEffect<R, A>(private val f: suspend EffectScope<R>.() -> A) : Effect<R, A> {
@Deprecated(
"This will be removed in Arrow 2.0",
level = DeprecationLevel.WARNING
)
internal class DefaultEffect<R, A>(val f: suspend EffectScope<R>.() -> A) : Effect<R, A> {
// We create a `Token` for fold Continuation, so we can properly differentiate between nested
// folds
override suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B =
Expand Down
Expand Up @@ -54,7 +54,10 @@ public interface EffectScope<in R> {
* ```
* <!--- KNIT example-effect-scope-02.kt -->
*/
public suspend fun <B> Effect<R, B>.bind(): B = fold(this@EffectScope::shift, ::identity)
public suspend fun <B> Effect<R, B>.bind(): B =
when (this) {
is DefaultEffect -> f(this@EffectScope)
}

/**
* Runs the [EagerEffect] to finish, returning [B] or [shift] in case of [R],
Expand Down
Expand Up @@ -21,6 +21,7 @@ import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
import kotlin.coroutines.startCoroutine
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class EffectSpec :
StringSpec({
Expand Down Expand Up @@ -241,8 +242,27 @@ class EffectSpec :
}.runCont()
} shouldBe Either.Left(e)
}

"#2760 - dispatching in nested Effect blocks does not make the nested Continuation to hang" {
checkAll(Arb.string()) { msg ->
fun failure(): Effect<Failure, String> = effect {
withContext(Dispatchers.Default) {}
shift(Failure(msg))
}

effect<Failure, Int> {
failure().bind()
1
}.fold(
recover = { it },
transform = { fail("Should never come here") },
) shouldBe Failure(msg)
}
}
})

private data class Failure(val msg: String)

suspend fun currentContext(): CoroutineContext = kotlin.coroutines.coroutineContext

internal suspend fun Throwable.suspend(): Nothing = suspendCoroutineUninterceptedOrReturn { cont ->
Expand Down

0 comments on commit 6c0fc8c

Please sign in to comment.