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

Inference issue with nested async boundaries #804

Open
fwbrasil opened this issue Oct 31, 2024 · 3 comments
Open

Inference issue with nested async boundaries #804

fwbrasil opened this issue Oct 31, 2024 · 3 comments
Labels
💎 Bounty bug Something isn't working

Comments

@fwbrasil
Copy link
Collaborator

The inference of Boundary when two operations are directly nested like Async.run(Async.timeout(1.second)(v)) is failing to compile. Background: #797 (comment)

@fwbrasil fwbrasil added the bug Something isn't working label Oct 31, 2024
hearnadam pushed a commit that referenced this issue Oct 31, 2024
…messages (#805)

I couldn't find a fix for #804. We
might need to restructure how we encode boundaries to support it. This
PR adds pending tests and better error reporting in case of issues to
infer the boundary.
@hearnadam
Copy link
Collaborator

I believe the issue is caused by using automatically propagating Boundaries between functions where the type may have changed, eg timeout (adds a failure type).

The fix is to derive the boundary within the function where the type already contains the expected value. The only issue is that the function must now be inline to expose Ctx type to the underlying macro.

    inline def timeout[E, A: Flat, Ctx](after: Duration)(v: => A < (Abort[E] & Async & Ctx))(
        using frame: Frame
    ): A < (Abort[E | Timeout] & Async & Ctx) =
        if !after.isFinite then v
        else
            summon[Boundary[Ctx, Async & Abort[E | Timeout]]] { (trace, context) =>
                Clock.use { clock =>
                    IO.Unsafe {
                        val sleepFiber = clock.unsafe.sleep(after)
                        val task       = IOTask[Ctx, E | Timeout, A](v, trace, context)
                        sleepFiber.onComplete(_ => discard(task.complete(Result.fail(Timeout(frame)))))
                        task.onComplete(_ => discard(sleepFiber.interrupt()))
                        Async.get(task)
                    }
                }
            }
    end timeout

@hearnadam
Copy link
Collaborator

/bounty $75 for a fix that doesn't require inlining the full body of each function

Copy link

algora-pbc bot commented Nov 17, 2024

💎 $75 bounty • Kyo

Steps to solve:

  1. Start working: Comment /attempt #804 with your implementation plan
  2. Submit work: Create a pull request including /claim #804 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to getkyo/kyo!

Add a bountyShare on socials

fwbrasil added a commit that referenced this issue Nov 19, 2024
This PR applies the workaround identified by @hearnadam with an `inline`
indirection. I think we should still keep #804 open to explore a more
proper solution. Users might need to define methods with boundaries and
the workaround can be confusing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💎 Bounty bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants