Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Arrow result continuation broken #2875

Closed
ulfryk opened this issue Dec 24, 2022 · 4 comments
Closed

[BUG] Arrow result continuation broken #2875

ulfryk opened this issue Dec 24, 2022 · 4 comments

Comments

@ulfryk
Copy link

ulfryk commented Dec 24, 2022

Affected version: 1.1.2
Affected scope: arrow.core.continuations
Kotlin version: 1.7.21

Using result { … } comprehension and binding invokations of suspended functions/methods inside causes unexpected behaviour. Nested Result<Result<X>> values are returned in runtime - despite having Result<X> type in compile time.

Bug affects result { … } and result.eager { … }.
It does NOT affect nullable { … } / nullable.eager { … } or either { … } / either.eager { … }.

Code to reproduce an issue:

import arrow.core.continuations.result
import kotlinx.coroutines.delay

suspend fun main() {
    val ok = result { "whatever" }
    println("The OK Result is: $ok")

    val a = getV()
    println("The A Result is: $a")

    val b = result {
        delay(1)
        "whatever"
    }
    println("The B Result is: $b")

    val c = result {
        getV().bind()
    }
    println("The C Result is: $c")

    val d = result {
        val v = getV().bind()

        v + "__cont"
    }
    println("The D Result is: $d")

}

private suspend fun getV() = result {
    delay(1)
    "whatever"
}

Result of running above code:

The OK Result is: Success(whatever)
The A Result is: Success(Success(whatever))
The B Result is: Success(Success(whatever))
The C Result is: Success(Success(Success(whatever)))
Exception in thread "main" java.lang.ClassCastException: class kotlin.Result cannot be cast to class java.lang.String (kotlin.Result is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
	at com.fiatrepublic.pomerania.oauth2server.pkceimpl.EffectsIssueKt$main$$inlined$invoke-gIAlu-s$4$3.invokeSuspend(Effect.kt:0)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at arrow.core.continuations.FoldContinuation.resumeWith(Effect.kt:713)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:178)
	at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
	at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
	at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
	at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
	at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:518)
	at kotlinx.coroutines.EventLoopImplBase$DelayedResumeTask.run(EventLoop.common.kt:500)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
	at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:108)
	at java.base/java.lang.Thread.run(Thread.java:830)

Process finished with exit code 1
@nomisRev
Copy link
Member

nomisRev commented Dec 24, 2022

Hey @ulfryk,

Thank you for the bug report, including reproducible examples 🙏
I saw you mentioned Affected version: 1.1.2, is this also reproducible in 1.1.3 and/or 1.1.4-rc.3?

@ulfryk
Copy link
Author

ulfryk commented Dec 24, 2022

Hey @nomisRev,

Checked other versions - 1.1.3 has same issue :( but 1.1.4-rc.3 seems to have it fixed 🎉 :

1.1.3

The OK Result is: Success(whatever)
The A Result is: Success(Success(whatever))
The B Result is: Success(Success(whatever))
The C Result is: Success(Success(Success(whatever)))
Exception in thread "main" java.lang.ClassCastException: class kotlin.Result cannot be cast to class java.lang.String (kotlin.Result is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
	at com.fiatrepublic.pomerania.oauth2server.pkceimpl.ArrowIssuesKt$main$$inlined$invoke-gIAlu-s$4.invokeSuspend(result.kt:0)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at arrow.core.continuations.FoldContinuation.resumeWith(Effect.kt:756)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
	at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:178)
	at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
	at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
	at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
	at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
	at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:518)
	at kotlinx.coroutines.EventLoopImplBase$DelayedResumeTask.run(EventLoop.common.kt:500)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
	at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:108)
	at java.base/java.lang.Thread.run(Thread.java:830)

Process finished with exit code 1

1.1.4-4c.3

The OK Result is: Success(whatever)
The A Result is: Success(whatever)
The B Result is: Success(whatever)
The C Result is: Success(whatever)
The D Result is: Success(whatever__cont)

Process finished with exit code 0

@nomisRev
Copy link
Member

@ulfryk thanks for letting us know ☺️ We're currently rolling out 1.1.4, and will be released this week.
Will close this issue after it's officially released.

@nomisRev
Copy link
Member

This fix has been released ☺️ Closing the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants