Skip to content
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

Attributes to indicate Send/Sync bound for Future generated in Static Async Trait #9

Open
umgefahren opened this issue Jul 25, 2022 · 3 comments

Comments

@umgefahren
Copy link

Motivation

As previously discussed it's a debated issue how to express Send/Sync bounds on the generated associated types for async methods. As I understand it, this issue will be resolved in the future. I'm currently writing a library which might profit from a way to express the bound so I would appreciate a solution for the problem to be stabilized along with static-async-trait.

Details

I'm currently developing a macro library that tries to implement about the same desugaring as described in the RFC. I came up with a solution for this using attributes on the trait methods.

Example

struct Foo;

trait Bar {
    #[send]
    async fn wait(&self);
}

impl Bar for Foo {
    async fn wait(&self) {
        todo!()
    }
}

// this trait can now be used with tokio::spawn
async fn spawn_trait<T: Bar + Sync + Send + 'static>(foo: T) {
    let handle = tokio::spawn(async move {
        foo.wait().await;
    });
    handle.await;
}

A method with a body that has to be Send is just annotated with #[send] and for Sync it's just annotated with #[sync].

An attribute would not be that unusual. Derive default enum uses an attribute as well.

Caveats

How would this appear in rustdoc?

I would appreciate your feedback

@umgefahren
Copy link
Author

Some additional thoughts:

I saw a proposal that suggested introducing additional, potentially complex, syntax. This aligns more with the general way how Rust deals with types, traits and especially trait constraints. Despite this being a huge implementation undertaking it wouldn't improve readability and make Rust even more complex.

In my opinion this is also a counter argument for just solving the issue by suggesting manual desugarization.

Since one can already do that as soon as GATs and impl traits are stabilized, this feature should be considered more as a quality of life improvement or syntactic sugar. As such I would consider introducing new as syntax overkill. Solving this in a fashion that resembles the macros currently used would benefit from better accessibility and readability. It would also speed up adaption once it's stabilized.

@tmandry
Copy link
Member

tmandry commented Aug 3, 2022

A downside of this approach is that Send/Sync-ness has to be decided on the trait. This is especially difficult for standard traits like AsyncIterator, and we don't want to have multiple versions of each trait (like we already do for async/sync).

@umgefahren
Copy link
Author

Thanks for the response!

I get why it was considered to introduce new syntax. However it might be useful to let the trait decide in some situations.

However I see why my proposal is unfit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants