-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Inconsistency in Send/Sync requirements for async/await #59245
Comments
I think this is working as intended-- I'd expect that in order for the future to be |
I guess it's also worth pointing out that what isn't "working as intended" here is that the reference in question shouldn't need to be held across the |
Actually, if the reference points to inside the future itself, I think that the pointed-to stuff might only need to be |
FYI, I was posted in internals for a similar issue regarding pattern matches. #![feature(
await_macro,
async_await,
futures_api,
optin_builtin_traits
)]
use std::future::Future;
struct Foo;
impl Foo {
fn foo(&self) -> Option<()> { Some(()) }
}
impl !Sync for Foo{}
async fn bar() {
let f = Foo;
if let Some(v) = f.foo() {
await!(async{})
}
}
async fn buz(f: impl Future<Output=()> + Send) {
await!(f)
}
fn main(){
buz(bar());
} |
I believe this is a duplicate of #57017. |
I'm not sure this is the same as #57017, but it does look similar -- will let someone more knowledgeable than me about compiler internals choose whether to close this :) |
It seems like #57017 is more specifically about a code pattern that leads to this happening, the underlying issue here is just that a generator holding a self-reference across a yield point requires the referenced object to be |
Minimised example (playground): #![feature(async_await)]
async fn foo(x: Box<dyn Send>) {
async fn bar() {}
let x = &x;
bar().await;
}
fn assert_send<T: Send>(_: T) {}
fn main() {
assert_send(foo(Box::new(5)));
}
|
I've just hit this again, with this: use std::cell::Cell;
use std::future::Future;
#[derive(Clone)]
struct NonSend {
foo: Cell<()>,
}
impl NonSend {
fn get_send(&self) -> Result<&(), ()> {
Ok(&())
}
}
async fn bar() {}
async fn foo() -> () {
let ns = NonSend { foo: Cell::new(()) };
loop {
match ns.get_send() {
Ok(r) => return *r,
Err(_) => bar().await,
}
}
}
pub fn assert_send() -> impl Send + Future<Output = ()> {
foo()
} Given that #57017 appears to be in the process of living again, maybe this should be made live again? (note: I have literally no idea how labels work for async/await) |
This results in wartiness, and currently misleading compiler help, when structuring generic async code: use std::fmt::Display;
async fn run(mut state: impl Display) {
do_stuff(&state).await;
// ...
}
async fn do_stuff(state: &impl Display) {
println!("{state}");
}
fn spawn_task<T>(state: T)
where
T: Display + Send + 'static,
{
tokio::spawn(run(state));
} The compiler produces an error and further suggests:
The non-restrictive solution is to make the reference passed to |
If a coroutine only captures Probably needs a new auto trait to opt out references, specifically used by coroutines. Something like I hit this issue today with a huge chunk of async code. I am not looking forward to refactoring it. |
The originally-reported example in this issue now works, as do the later minimizations. So I'm going to close this issue, as it seems resolved. If you're still hitting an issue, it may be something different, so please file a new issue and provide a minimized example if possible. |
My example still fails as of rustc 1.84.0-nightly (705cfe0 2024-11-01). Should I file a separate issue? |
We discussed adding a diagnostic for that over in: If you have further thoughts about that, they should probably just go there. In terms of filing it as an ask that it "just work" somehow, I don't personally see how that could ever be supported in general. It's probably just worth tracking it in #129105 for now, unless you see some smaller special case that could conceivably be supported and want to file that separately. |
The following code, when switching between lines 14 and 15 (the two versions of the
for
line), oscillates between compiling and not compiling because it requiresSync
for thedyn Send
items:(playground)
(Note: this is a simplification of the failure that occurs on Ekleog/erlust@98c6cbc when running
cargo test
)The text was updated successfully, but these errors were encountered: