-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Question: Any reason to demand Sync for Rust async host function? #10262
Comments
Thanks, this is a great question that I've been wrestling with as well so hopefully this explanation helps you and others who run into this. The quick answer is: this restriction is not always ideal but its essentially required for Wasmtime to interoperate with the Rust async ecosystem, and lifting it would create considerable difficulty throughout the Wasmtime ecosystem. Its an unfortunate problem I've run into a bunch, especially as I'm currently working on no_std based single-threaded embeddings for wasmtime, but I don't have a satisfactory way to resolve it. If you are using Wasmtime in a single-threaded context, we currently don't have a better answer than to lie to the type system and write Here's lots more details, possibly more details than you need: Wasmtime's async support exists so that Wasmtime can be embedded in async Rust applications. While. not all async Rust applications use an executor that requires Futures which are Send, in practice, many of our production users are using the Tokio ecosystem and have a hard requirement on Tokio's multi-threaded scheduling in order to maximize the capacity of their systems. Wherever possible, we have kept Wasmtime's interfaces agnostic on requiring Send types. For example, the However, if you use Now, you might point out that, like we sometimes see in the various Rust async ecosystems, there could be a limiter_async_local variant of that method which doesn't have the Send constraint so that users could pick whether they are Send or not. This might be possible, but each case we do this for would increase the complexity of Wasmtime's implementation, and there end up being many such cases all throughout Wasmtime - the ResourceLimiterAsync is just one example. You might also notice things like, hey, over in the plain old synchronous So, now that I've laid out how Send is infectious in not just the async Wasmtime apis but also in other places, we can generalize that to the futures returned by those Host methods - thats just table stakes for running on an async runtime. When it comes to the constraint put on the type T that impls Host itself (rather than the Futures that methods on T return), that comes down to the the ResourceTable abstraction: any value that the resource table is given ownership of (via I want to conclude that I sympathize with this Send infection making Wasmtime difficult to program with in situations where you cannot, or don't want to, impl Send on the structures interacting with Wasmtime. I'm working directly in those situations, and I don't like that I end up sprinkling At the end of the day, the best answer I have is, this isnt the sort of property that Rust's type system lets us make parametric or truly "zero cost" to the programmer, without costs to the wasmtime project that we as maintainers couldn't stomach. So we had to pick one side and live with the fallout. We picked interoperability with Tokio because some important production uses (including me, years ago) demanded it, and that means other users (including me, now) have to unfortunately live with it. |
Hi @pchickey thanks a lot for your explanation in great details, now I totally understand it, that's the trade-off we have to pay to keep a maintable system, which is fair enough. Then I'll try to find some workaround in my own code to make type checker happy |
I'll close this but if you or anyone has further questions feel free to continue discussion here. |
Hi @pchickey thanks very much for your detailed explanation! I know why |
Sync ends up being a constraint for essentially all of the same reasons that Send does, but I'm not sure that I understand the question. What is task_local and how are you using it that is unable to compile? |
For multi-thread runtimes, only As far as I know, the |
And for
task_local! {
static CTX: RefCell<Context>;
}
CTX.scope(RefCell::new(Context::new()), async { inner future here }).await; Because there's a |
Hi, I got a trouble when calling another async function within WIT async host function because my function depends on a
task_local
storage which is notSync
, and I found that wit-bindgen generate host function with following signature:Is is possible to loose this restriction?
The text was updated successfully, but these errors were encountered: