Repository navigation
Missing detection of Send for async fn #53259
Copy link
Copy link
Closed
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-coroutinesArea: CoroutinesArea: CoroutinesC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
The following async function appears to not implement Send: (simpler reproducer at second post from @Nemo157 using generators)
pub async fn __receive() -> ()
{
let mut chan: futures::channel::mpsc::Receiver<Box<Send + 'static>> = None.unwrap();
await!(chan.next());
}As futures::channel::mpsc::Receiver has an impl of Send+Sync when its generic parameter is Send, and Box<Send + 'static> is Send, I would expect the future returned by this function to be Send. However, when trying to require it, I get:
error[E0277]: `dyn std::marker::Send` cannot be sent between threads safely
--> erlust/src/lib.rs:30:9
|
30 | spawn(__receive());
| ^^^^^ `dyn std::marker::Send` cannot be sent between threads safely
|
= help: the trait `for<'r> std::marker::Send` is not implemented for `dyn std::marker::Send`
= note: required because of the requirements on the impl of `for<'r> std::marker::Send` for `std::ptr::Unique<dyn std::marker::Send>`
= note: required because it appears within the type `std::boxed::Box<dyn std::marker::Send>`
= note: required because of the requirements on the impl of `for<'r> std::marker::Send` for `futures::channel::mpsc::Inner<std::boxed::Box<dyn std::marker::Send>>`
= note: required because of the requirements on the impl of `for<'r> std::marker::Send` for `std::sync::Arc<futures::channel::mpsc::Inner<std::boxed::Box<dyn std::marker::Send>>>`
= note: required because it appears within the type `futures::channel::mpsc::Receiver<std::boxed::Box<dyn std::marker::Send>>`
= note: required because it appears within the type `for<'r, 's, 't0> {futures::channel::mpsc::Receiver<std::boxed::Box<(dyn std::marker::Send + 'r)>>, futures::stream::Next<'s, futures::channel::mpsc::Receiver<std::boxed::Box<(dyn std::marker::Send + 't0)>>>, ()}`
= note: required because it appears within the type `[static generator@erlust/src/lib.rs:18:1: 22:2 for<'r, 's, 't0> {futures::channel::mpsc::Receiver<std::boxed::Box<(dyn std::marker::Send + 'r)>>, futures::stream::Next<'s, futures::channel::mpsc::Receiver<std::boxed::Box<(dyn std::marker::Send + 't0)>>>, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@erlust/src/lib.rs:18:1: 22:2 for<'r, 's, 't0> {futures::channel::mpsc::Receiver<std::boxed::Box<(dyn std::marker::Send + 'r)>>, futures::stream::Next<'s, futures::channel::mpsc::Receiver<std::boxed::Box<(dyn std::marker::Send + 't0)>>>, ()}]>`
= note: required because it appears within the type `impl futures::Future`
= note: required because it appears within the type `impl futures::Future`
I am not 100% sure this issue is actually tied to async/await, but removing the await! makes the issue vanish, so… cc #50547
A full reproducer can be found here, but unfortunately doesn't compile on the playground due to lack of futures-0.3.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-coroutinesArea: CoroutinesArea: CoroutinesC-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Activity
Nemo157 commentedon Aug 11, 2018
Simpler repro using generators directly (playground):
It seems the issue is that
dyn Sendis notfor<'r> Send, but I have no idea why that is.elinorbgr commentedon Aug 13, 2018
Interestingly, this simpler example compiles fine:
So
dyn Sendis actuallySend, but in the context of generators, rustc seems to fail to realize that?withoutboats commentedon Aug 13, 2018
@Nemo157's error is very surprising, since I thought @cramertj had correctly identified the error here on the tracking issue:
That is, I thought a reference to receiver was being stored in its state because of the way the
await!(chan.next())was being expanded. I've been vaguely afraid that this problem would crop up: internal references in async fn should beSendbecause they're safely encapsulated here. I'm not sure how often this will appear as a problem, so far no one's reported it (unless that's what underlies this issue, but it doesn't look like it).However, @Nemo157's is much more surprising
dyn Sendcertainly does implementSend; a core part of being an object-safe trait is thatdyn Trait: Traitholds. It's certainly a bug.Ekleog commentedon Aug 13, 2018
For the record,
futures::channel::mpsc::ReceiverisSend+Syncwhen the wrapped type isSend, even though thestdone isn't. So that problem hopefully shouldn't crop up in this specific case at least :)Ekleog commentedon Aug 21, 2018
Potentially related issue: #53548 (has the same
for<'r>bound appearing out of seemingly nowhere)nikomatsakis commentedon Feb 22, 2019
Does not reproduce if you don't use
dyn Send. For example this works (playground):nikomatsakis commentedon Feb 22, 2019
Using
dyn Foo + Sendalso works -- @Ekleog can you share a bit of where this example came from?Ekleog commentedon Feb 22, 2019
@nikomatsakis Looks like this issue has been fixed! It's one of the few issues I raised while trying to get code using a macro that expands to this to generate code that builds correctly. Basically, I've been minimizing the example to come up with this specific issue.
As another minimized error was #53548 that isn't fixed yet I'd assume the overall code doesn't build yet, but I'll make sure to open another issue if I can minimize the original example to another reasonably small code chunk. I think this issue can be closed for now. Thank you! :)