-
-
Notifications
You must be signed in to change notification settings - Fork 86
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
Future type returned by trait methods should impl Sync #77
Comments
I am working on this |
fixes dtolnay#77 Sponsored-by: 49nord GmbH
fixes dtolnay#77 Sponsored-by: 49nord GmbH
As discussed in the linked topic, the
And that's totally fine! Trying to make everything
Yes, that one is the issue |
That's exactly the case we ran into, and the reason why I opened #96 . I agree it's not pretty, but I don't see another solution ATM. |
I think you can wrap the Here is another discussion around the same topic: Matthias247/futures-intrusive#23 |
To link together more related discussions, there is also a proposal stemming from that same internals thread to define a type that behaves like a compile-time-checked mutex to make things
If the convention were for all For the sake of interoperability, it seems like either (A) all The part I didn't consider is that this change is not progress unless everyone agrees with solution (A). While Rusoto exposes its public API via I'm not sure which solution is ideal, but I hope the ecosystem can converge on one. Library users should not have to think about Sync when it doesn't actually mean anything for |
Yes please. If we can do it with classic traits, let's do it with async ones too :) Here's a simple example: use async_trait; // 0.1.36
fn test_ok<T:Classic>(tested:T) {
is_sync(tested.sync_ok());
}
fn test_nok<T:Modern>(tested:T) {
is_sync(tested.sync_nok());
}
fn is_sync<T: Sync>(_tested: T) {}
#[async_trait::async_trait]
trait Modern {
type Result;
async fn sync_nok(&mut self) -> Self::Result;
}
trait Classic {
type Result;
fn sync_ok<'s, 'f>(
&'s mut self,
) -> Box<dyn std::future::Future<Output = Self::Result> + 'f + Send + Sync>
where
's: 'f;
} |
Similarly, I may desire that the trait produces a future with static lifetime. Perhaps an additional attribute over the async fn could be used to optionally specify extra traits. Something similar to pin_project's #[async_trait::async_trait]
trait Modern {
type Result;
#[future_is['static + Sync]]
async fn sync_nok(&mut self) -> Self::Result;
}
trait Classic {
type Result;
fn sync_static(
&mut self,
) -> Box<dyn std::future::Future<Output = Self::Result> + 'static + Send + Sync>;
} |
Any update here? This is quite painful to work around atm |
I would prefer not to change this in this crate. But it would be reasonable for somebody else to maintain a more fully featured macro for async traits that handles this use case. |
It's coming folks :) https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-in-trait-nightly.html#when-it-does-happen just where to grab some patience :) |
The methods generated by this library return
Pin<Box<dyn Future + Send + 'async>>
but leave outSync
.As discussed on this internals thread, every type that may be used in async-await should be
Sync
. It may seem meaningless for aFuture
to implSync
since its only method (poll
) takes&mut self
so&Future
is useless, but the problem is that as an auto trait, the!Sync
propagates to anything that owns theFuture
.As a concrete example, I ran into this while trying to make a Hyper server that concatenates multiple objects from Amazon S3 into an HTTP response.
rusoto_s3
usesasync-trait
to define itsS3
trait.S3::get_object
returnsPin<Box<dyn Future + Send>>
, without Sync. When combining these futures into a stream, the resultingStream
therefore does not implSync
. However,hyper::Body::wrap_stream
has aSync
bound on its argument because the stream it is passed ends up wrapped inside aRequest
struct that needs to beSync
so that it can be borrowed across anawait
.The text was updated successfully, but these errors were encountered: