Stream: general

Topic: Marking function as async vs returning a future in P3


view this post on Zulip Mendy Berger (Jun 10 2026 at 20:37):

I'm trying to understand best practices around async vs future<T>, and when to choose each one.

Rust and JS - langs where I'm most comfortable - don't make a big difference between marking a function async vs returning a future/promise. Both have almost the same type (with only minor differences that don't affect most users).
See Rust and TypeScript examples of implementing the same functions either as async or as returning a future/promise

In wit, there seems to be a larger difference. E.g. wasmtime lets async functions be backed by a simple async rust function whereas future needs to be backed by FutureReader.

Since the semantics seem meaningfully different, what are the reasons to choose one over the other when designing a wit interface?

view this post on Zulip Alex Crichton (Jun 10 2026 at 20:45):

My recommendation would be to use async func until you have a reason not to

view this post on Zulip Mendy Berger (Jun 10 2026 at 21:04):

What would make a good reason not to use async?

view this post on Zulip Joel Dice (Jun 10 2026 at 21:06):

If the function takes a borrow handle to a resource, the borrow won't be released until the function returns. If it's an async function, that means you have to .await it before the borrow is released. If it's a sync function, you'll get the borrow back sooner and can defer awaiting the future as you please.

view this post on Zulip Joel Dice (Jun 10 2026 at 21:09):

Also, you might want to return e.g. tuple<something, future<something-else>>, which gives you more a bit more flexibility than an async function. Or you might even want an async function that returns a tuple with a future. You've got plenty of options :)

view this post on Zulip Mendy Berger (Jun 10 2026 at 21:16):

Thanks both!
If I can ask a follow up: what is the difference in semantics between async and future? Why is the wasmtime api so different with future?

view this post on Zulip Joel Dice (Jun 10 2026 at 21:22):

You can think of a future as a oneshot channel which includes a writable end and a readable end. The future type itself represents the readable end, and the only things you can do with it are read (i.e. await) it, drop it, or give it away (e.g. to the host or another component instance). Whereas the subtask produced by a call to an async function can be awaited or dropped, but it can't be given away.

view this post on Zulip Joel Dice (Jun 10 2026 at 21:24):

Another way of thinking about it is that future is for "unstructured" concurrency where you're wiring control flow up in a way that's not necessarily shaped like a call tree. Whereas recursive async function calls always end up forming a tree structure.

view this post on Zulip guest271314 (Jun 14 2026 at 16:43):

All I know is wasmtime kept throwing when I tried to use WASI P3 with andreiltd's componentize-qjs

Yeah, that looks like wasmtime issue, it seems that it doesn't flush stdout. I'm not sure if there is a guest side workaround but let me have a look.

https://github.com/andreiltd/componentize-qjs/issues/2#issuecomment-4689553760

view this post on Zulip Ralph (Jun 15 2026 at 11:28):

ah, the classic doesn't flush issue.....


Last updated: Jul 29 2026 at 05:03 UTC