async constructs (auto generated futures) should implement Sync unconditionally, as there is no way to get access to the inner data
without gaining mutable access
error: future cannot be shared between threads safely
--> src/main.rs:7:5
|
7 | / assert_send_sync(async {
8 | | let cell = Cell::new(0);
9 | | macro_rules! increment {
10 | | () => { cell.set(cell.get()+1) };
... |
20 | | assert_eq!(cell.get(), 14);
21 | | })
| |______^ future created by async block is not `Sync`
|
= help: within `{async block@src/main.rs:7:22: 7:27}`, the trait `Sync` is not implemented for `Cell<i32>`, which is required by `{async block@src/main.rs:7:22: 7:27}: Sync`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
note: future is not `Sync` as this value is used across an await
--> src/main.rs:17:24
|
8 | let cell = Cell::new(0);
| ---- has type `Cell<i32>` which is not `Sync`
...
17 | async { }.await;
| ^^^^^ await occurs here, with `cell` maybe used later
note: required by a bound in `assert_send_sync`
--> src/main.rs:5:35
|
5 | fn assert_send_sync<T: Send + Sync>(_: T) {}
| ^^^^ required by this bound in `assert_send_sync
this for example, means these futures can go in a Vec<Box<dyn Future+Sync>> that’s part of a larger data structure that needs to be Sync without requiring an additional wrapper like std::sync::Exclusive
I don't quite follow, I mean for the Send part of the future, that is still very much tracked, its just that all futures, weather they have non sync types or not, are still sync
The future itself will not become Send from !Send. Yes, some type that contains the reference to the future and previously !Send might become Send. But that doesn't break anything, it's just a direct consequence.
There's even a crate doing exactly this : sync_wrapper.
This would prevent any future addition of methods or impl of traits with methods taking &self to such futures, as then Sync would actually become wrong.
IMO if you need your Future to be Sync then use Exclusive instead. It implements Future, so you can use it everywhere a Future is expected.
That said, the future in your example is not only !Sync but also !Send, so neither Exclusive nor your proposal will make it compile. What you really need to make it compile is a weaker notion of Send for data that never escapes the future, but AFAIK this never got any formal proposal as it's very difficult to find a way to guarantee the requirement the the data "never escapes the future".
This would prevent any future addition of methods or impl of traits with methods taking &self to such futures, as then Sync would actually become wrong.
there is no way for you to use that &self, to get any data out of it, so no it would still be fine, and I really don't see extending opaque types as a future possibility, as the rust book says
Opaque types are a kind of type alias. They are called opaque because, unlike an ordinary type alias, most Rust code (e.g., the callers of as_u32s ) doesn't know what type AsU32sReturn represents. It only knows what traits that type implements (e.g., IntoIterator<Item = u32> ). The actual type that is inferred for AsU32sReturn is called the "hidden type".
so if the type really is hidden, I don't think there are plans to unhide it to make it possible extend
IMO if you need your Future to be Sync then use Exclusive instead. It implements Future, so you can use it everywhere a Future is expected.
Exclusive, is unstable, and is no where near being stable
That said, the future in your example is not only !Sync but also !Send , so neither Exclusive nor your proposal will make it compile. What you really need to make it compile is a weaker notion of Send for data that never escapes the future, but AFAIK this never got any formal proposal as it's very difficult to find a way to guarantee the requirement the the data "never escapes the future".
My point is that there is no way now. Implementing your suggestion would preclude adding any new way in the future, for example is any need for an optional &self method on Future is found.
Moreover the type of an async block is not opaque, it's just unnameable (just like the types of closures).
You are quoting the chalk book, which is not used in the rust compiler and likely never will.
If this proposal was implemented it likely wouldn't be immediately stable either.