Async block bounds in rustwasm / wasm-pack

I am writing a library that can be used from both native applications and web/wasm32 and I am wondering about the bounds created by the async block construct:

// Bounds on wasm_bindgen_futures::spawn_local are:
//     F: Future<Output = ()> + 'static,
wasm_bindgen_futures::spawn_local(async {
    // ...
});

// Bounds on tokio::spawn are:
//    T: Future + Send + 'static,
//    T::Output: Send + 'static,
tokio::spawn(async {
    // ...
});

The important difference is that wasm_bindgen::spawn_local doesn't have Send, and there is no non-local version of spawn.

So I created a shim for spawn, one for wasm32 and one for non-wasm32 like this:

pub trait Spawn {
    #[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
    fn spawn<Fut>(future: Fut)
    where
        Fut: Future<Output = ()> + 'static;

    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
    fn spawn<Fut>(future: Fut)
    where
        Fut: Future + Send + 'static,
        Fut::Output: Send + 'static;
}

And it works.

But why does compiling with wasm-pack make the async { block NOT be Send and comping for native makes it be Send?

I tried searching the internet for it, but can't find any documentation for that behavior. Can someone help me understand it?

By understand I mean "where is the technical documentation for this", not "because wasm32 doesn't have threads in a browser".

It doesn't do this. The function is not able to change whether something is Send. Instead, it accepts both futures that are Send, and those that are not.

Adding a + Send to the function will make it accept only futures that are Send.

I think I understand now, thanks @alice !

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.