You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is a problem I kept running into with async functions with something like Axum/Hyper.
With the async function syntax, it is very easy for its output Future to accidentally not be Send because the compiler thinks you are holding onto something that is not Send across an await point. One example would be a (synchronous/blocking) MutexGuard.
For example:
pubstructFoo<T:Send + Clone + Default>{shared:Arc<Mutex<T>>,}impl<T:Send + Clone + Default>Foo<T>{pubasyncfnthis_is_correctly_send(&self) -> T{let thing = self.shared.lock().unwrap().clone();sleep(Duration::from_secs(1)).await;
thing
}pubasyncfnthis_is_also_send(&self) -> T{let thing = {letmut guard = self.shared.lock().unwrap();
mem::replace(guard.deref_mut(),T::default())};sleep(Duration::from_secs(1)).await;
thing
}pubasyncfnthis_is_accidentally_not_send(&self) -> T{letmut guard = self.shared.lock().unwrap();let thing = mem::replace(guard.deref_mut(),T::default());// As of now, whether this drop is here makes no difference to the compiler// Eventually, -Zdrop-tracking will change thatdrop(guard);sleep(Duration::from_secs(1)).await;
thing
}}
This matters because the !Send-ness can propagate up very far and eventually when mounting the handler to something like the Axum router, it causes a cryptic error and takes a long time to trace back to where the problem is.
To guard against these kind of issues, I can do something like this (a bit simplified):
implFoo{asyncfnfoo(){// ...}#[allow(dead_code)]fn__foo_must_be_send(&self){#![allow(unused_must_use)]fnit_sends<T:Send>(it:T) -> T{
it
}it_sends(self.foo());}}
This works but is pretty distracting. It would be nice to be able to do something like:
implFoo{#[assert_impl(Send)]asyncfnfoo(){// ...}}
While looking for something that does that, this crate came up. Does something like that seem like a good fit for this crate, or are there some reasons why it is not possible/not a good fit?
The text was updated successfully, but these errors were encountered:
There is a problem I kept running into with async functions with something like Axum/Hyper.
With the async function syntax, it is very easy for its output Future to accidentally not be
Send
because the compiler thinks you are holding onto something that is notSend
across an await point. One example would be a (synchronous/blocking)MutexGuard
.For example:
Some related background information:
-Zdrop-tracking
by default rust-lang/rust#97331This matters because the
!Send
-ness can propagate up very far and eventually when mounting the handler to something like the Axum router, it causes a cryptic error and takes a long time to trace back to where the problem is.To guard against these kind of issues, I can do something like this (a bit simplified):
This works but is pretty distracting. It would be nice to be able to do something like:
While looking for something that does that, this crate came up. Does something like that seem like a good fit for this crate, or are there some reasons why it is not possible/not a good fit?
The text was updated successfully, but these errors were encountered: