Currently #[clear]
(and maybe also #[set]
) do not enforce that as this compiles:
#[async_auto_traits::clear]
async fn foo() {}
fn assert_send(_: impl Send) {}
fn main() {
assert_send(foo());
}
Because impl Future
does not hide auto traits.
The enforcement could be done through something like this (play):
use pin_project_lite::pin_project;
use std::{
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
pin_project! {
pub struct NotSendButSyncFuture<F: Future> {
#[pin]
future: F,
ghost: PhantomData<*const ()>,
}
}
unsafe impl<F: Future + Sync> Sync for NotSendButSyncFuture<F> {}
impl<F: Future> NotSendButSyncFuture<F> {
pub fn new(future: F) -> Self {
Self {
future,
ghost: PhantomData,
}
}
}
impl<F: Future> Future for NotSendButSyncFuture<F> {
type Output = F::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.project().future.poll(cx)
}
}
fn foo() -> impl Future {
NotSendButSyncFuture::new(async move { todo!() })
}
fn assert_send(_: impl Send) {}
fn main() {
assert_send(foo());
}
Or something like this (but may not work properly for async fn
s that have no .await
, play):
use std::{future, marker::PhantomData};
async fn foo() {
let _phantom = PhantomData::<*mut ()>;
future::ready(()).await;
}
fn assert_send_sync(_: impl Send + Sync) {}
fn main() {
assert_send_sync(foo());
}
(Moved from rust-lang/rust#82187 (comment), sorry for being off-topic there!)