Stream: beginners

Topic: async platforms?


view this post on Zulip Raz (Jun 15 2026 at 22:41):

Hello everyone, I'm new here and just finished reading about the platforms in the documentation website
It seems roc platforms would be a good fit for asynchronous io
Does one exist? Or is there a proposal for one?

view this post on Zulip Richard Feldman (Jun 15 2026 at 22:58):

welcome! The short answer is that platforms are already able to do async I/O, but implementing it with good performance is very advanced and we don't have a good example of doing it end to end yet :smile:

view this post on Zulip souf (Jun 16 2026 at 05:15):

@Richard Feldman we could have some implementation in roc, for example an event loop implemented in roc directly?

view this post on Zulip Raz (Jun 16 2026 at 08:10):

@souf that sounds backwards, I imagined the platform implements the event loop but only exports functions like gather, race, etc

view this post on Zulip souf (Jun 16 2026 at 09:22):

@Raz why would it be backwards?

view this post on Zulip souf (Jun 16 2026 at 09:23):

Having the platform doing it would require each platform to re-implement it, and potentially more complex types to make it ergonomic and compatible with a wide range of async operations/erros, etc... between the platform and roc. Having roc doing it, it would probably be simpler, and you gain compatibility with all platforms by doing it once and less platform specifics.

view this post on Zulip souf (Jun 16 2026 at 09:51):

What I think is that the platform could expose something like that:

## Spawns a function returning `a` future that can be awaited
run_async! : (() => a) => Future a

## Waits for at least one of the given futures completes.
##  returns the future that completed and its value.
wait_any! : List (Future a) => (Future a, a)

wait_any rather than just wait otherwise you would not be able to implement race efficiently.

From here, race, all, etc... is just pure logic around it.

view this post on Zulip souf (Jun 16 2026 at 09:57):

Not sure what it involves as I haven't worked with platform yet thought, but I'm very interested in having such a feature.

view this post on Zulip souf (Jun 16 2026 at 10:13):

Actually with this approach there is a loop in Roc, and potentially one in the underlying platform calls (that does the optimized waiting). So I'm not even sure how to call this. Is the roc part supposed to be called an "event loop"?

view this post on Zulip Luke Boswell (Jun 16 2026 at 11:06):

I asked Claude to do some exploration and give a summary based on old discussions here in zulip... I'm not sure this is super accurate as it's been a while since we've talked about this or done any experiments but it mostly looks ok to me https://gist.github.com/lukewilliamboswell/304c57045fa0116c1a94a1baddcaf469

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:03):

yeah I'd say the "Mechanism 1" section is the most relevant - that prototype it links to is how we can have a Go-style experience of "I/O is automatically nonblocking without needing to write async or await"

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:04):

I think it's better overall than actual async/await both because it gets rid of the ceremony of writing "async" and "await" all over the place (while still getting you the concurrency benefits) but also because you get real stack traces without having to pay an insane up-front performance cost

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:05):

it's already possible today to implement a host that does this, but it's a lot of work :smile:

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:06):

I want to work on that sometime after the 0.1.0 launch (which is on track to be later this year)

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:06):

because separately from the host stuff to get the nonblocking I/O, we do actually need some compiler changes to be able to do the equivalent of a type-safe Promise.all from JS

view this post on Zulip souf (Jun 16 2026 at 13:07):

Richard Feldman said:

you get real stack traces without having to pay an insane up-front performance cost

why would the performance cost be so big?

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:07):

so I want to do that work together with the host work and have concurrency be a major theme of the 0.2.0 release

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:24):

souf said:

Richard Feldman said:

you get real stack traces without having to pay an insane up-front performance cost

why would the performance cost be so big?

without going too deep down the coroutines rabbit hole:

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:26):

so I think for us, the "stackful" approach is better.

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:27):

separately, there's the question of how to hook into hosts that are using async, such as JS in the browser where effects like http requests are unavoidably async even if that's not what we're compiling directly to

view this post on Zulip Richard Feldman (Jun 16 2026 at 13:32):

in general, it's possible for us to do this stackful coroutines approach and then hook into the host's async machinery. On non-wasm targets, this can theoretically be pretty fast, although we'd need a working implementation to properly verify that.

On wasm, it's currently possible but slow because wasm's stack switching proposal (which was in Phase 2 last I checked) hadn't landed yet https://effect-handlers.org/talks/stack-switching-wasmcg-feb2025.pdf

view this post on Zulip souf (Jun 16 2026 at 13:49):

Thanks for the nice explanation! Is that related to the fact that rust requires to pass a cli flag explicitly to enable stack traces?

view this post on Zulip Richard Feldman (Jun 16 2026 at 14:49):

I don't think so, actually

view this post on Zulip Richard Feldman (Jun 16 2026 at 14:50):

I think that applies to synchronous code, and I suspect it's more about whether there's a signal handler set up that collects backtraces on stack overflows (and other OS signals, like segfaults) as opposed to just doing the default thing of exiting (which might be what you want, in case for example your program is setting up its own signal handling and you don't want Rust to inject its own signal handling that could interfere with that)

view this post on Zulip Romain Lepert (Jun 16 2026 at 19:16):

Richard Feldman said:

in general, it's possible for us to do this stackful coroutines approach and then hook into the host's async machinery. On non-wasm targets, this can theoretically be pretty fast, although we'd need a working implementation to properly verify that.

On wasm, it's currently possible but slow because wasm's stack switching proposal (which was in Phase 2 last I checked) hadn't landed yet https://effect-handlers.org/talks/stack-switching-wasmcg-feb2025.pdf

WASI 0.3 is all about the Component Model's async ABI
https://bytecodealliance.org/articles/WASI-0.3
https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#concurrency

So it seems to made quite some progress.

view this post on Zulip Richard Feldman (Jun 16 2026 at 19:16):

oh I'm talking about wasm in the browser, not wasi :smile:

view this post on Zulip Richard Feldman (Jun 16 2026 at 19:17):

and the stack switching thing is what we really need, not async ABI

view this post on Zulip Richard Feldman (Jun 16 2026 at 19:18):

nothing wrong with wasi or anything, just that it doesn't help with the browser use case

view this post on Zulip Romain Lepert (Jun 16 2026 at 20:44):

ah right, of course

view this post on Zulip Raz (Jun 17 2026 at 12:55):

Is there a written design proposal for async platforms I can read through?
Or is it too early?

view this post on Zulip souf (Jun 17 2026 at 14:28):

@Raz I think everything that exists is in the summary sent by Luke: https://gist.github.com/lukewilliamboswell/304c57045fa0116c1a94a1baddcaf469


Last updated: Jul 23 2026 at 13:15 UTC