# Pre-RFC async constructs (auto generated futures) should implement Sync unconditionally

**URL:** <https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141>\
**Category:** language design\
**Created:** [July 7, 2024, 7:07pm UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141 "2024-07-07T19:07:44Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vrtgs](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vrtgs/32/12316_2.png) [@Vrtgs](https://internals.rust-lang.org/u/Vrtgs)\
**Post date:** [July 7, 2024, 7:07pm UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/1 "2024-07-07T19:07:44Z")

</div>

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

currently this fails even though it shouldn't

```rs
fn should_compile() {
    use std::cell::Cell;

    fn assert_send_sync<T: Send + Sync>(_: T) {}

    assert_send_sync(async {
        let cell = Cell::new(0);
        macro_rules! increment {
            () => { cell.set(cell.get()+1) };
        }
        
        increment!();
        increment!();

        for _ in 0..10 {
            increment!();
            async { }.await;
        }

        assert_eq!(cell.get(), 12);
    })
}

```

```rust
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](https://doc.rust-lang.org/std/sync/struct.Exclusive.html)

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [July 7, 2024, 7:12pm UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/2 "2024-07-07T19:12:20Z")

</div>

That raises a question: what should happen if an async fn incorporates raw pointers, or other non-threadsafe types?

---

<div class="post-metadata">

**Author:** ![Vrtgs](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vrtgs/32/12316_2.png) [@Vrtgs](https://internals.rust-lang.org/u/Vrtgs)\
**Post date:** [July 7, 2024, 7:21pm UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/3 "2024-07-07T19:21:19Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [July 8, 2024, 9:40am UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/4 "2024-07-08T09:40:18Z")

</div>

Sounds like that would make types `Send` that shouldn't have that marker trait in the first place, no different from sync Rust.

---

<div class="post-metadata">

**Author:** ![zirconium-n](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zirconium-n/32/9078_2.png) [@zirconium-n](https://internals.rust-lang.org/u/zirconium-n)\
**Post date:** [July 8, 2024, 10:05am UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/5 "2024-07-08T10:05:00Z")

</div>

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](https://docs.rs/sync_wrapper/latest/sync_wrapper/).

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [July 8, 2024, 10:10am UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/6 "2024-07-08T10:10:59Z")

</div>

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".

---

<div class="post-metadata">

**Author:** ![Vrtgs](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vrtgs/32/12316_2.png) [@Vrtgs](https://internals.rust-lang.org/u/Vrtgs)\
**Post date:** [July 8, 2024, 10:30am UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/7 "2024-07-08T10:30:23Z")

</div>

> 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](https://rust-lang.github.io/chalk/book/clauses/opaque_types.html)

> 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".

yeah fair enough, I've since updated the post

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [July 8, 2024, 11:15am UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/8 "2024-07-08T11:15:20Z")

</div>

> [@Vrtgs](#):
>
> there is no way for you to use that &self, to get any data out of it

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).

> [@Vrtgs](#):
>
> as [the rust book says](https://rust-lang.github.io/chalk/book/clauses/opaque_types.html)

You are quoting the chalk book, which is not used in the rust compiler and likely never will.

> [@Vrtgs](#):
>
> Exclusive, is unstable, and is no where near being stable

If this proposal was implemented it likely wouldn't be immediately stable either.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [October 6, 2024, 11:16am UTC](https://internals.rust-lang.org/t/pre-rfc-async-constructs-auto-generated-futures-should-implement-sync-unconditionally/21141/9 "2024-10-06T11:16:00Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
