Skip to content
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

Tracking issue for #![feature(async_closure)] (RFC 2394 / RFC 3668) #62290

Open
4 of 7 tasks
Tracked by #1568
Centril opened this issue Jul 2, 2019 · 35 comments
Open
4 of 7 tasks
Tracked by #1568

Tracking issue for #![feature(async_closure)] (RFC 2394 / RFC 3668) #62290

Centril opened this issue Jul 2, 2019 · 35 comments
Labels
A-async-await Area: Async & Await A-closures Area: closures (`|args| { .. }`) AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-RFC-implemented Blocker: Approved by a merged RFC and implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-async_closure `#![feature(async_closure)]` requires-nightly This issue requires a nightly compiler in some way. S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue. WG-async Working group: Async & await

Comments

@Centril
Copy link
Contributor

Centril commented Jul 2, 2019

This is a tracking issue for #![feature(async_closure)] (rust-lang/rfcs#2394).
The feature gate provides the async |...| expr closure syntax.

As with all tracking issues for the language, please file anything unrelated to implementation history, that is: bugs and design questions, as separate issues as opposed to leaving comments here. The status of the feature should also be covered by the feature gate label. Please do not ask about developments here.

Steps:

Open questions (RFC 2394)

Open questions (RFC 3668)

Related

@Centril Centril added B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. A-closures Area: closures (`|args| { .. }`) T-lang Relevant to the language team, which will review and decide on the PR/issue. B-unstable Blocker: Implemented in the nightly compiler and unstable. B-RFC-implemented Blocker: Approved by a merged RFC and implemented. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. A-async-await Area: Async & Await AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. labels Jul 2, 2019
Centril added a commit to Centril/rust that referenced this issue Jul 4, 2019
…mertj

Move `async || ...` closures into `#![feature(async_closure)]`

The `async || expr` syntax is moved out from `#![feature(async_await)]` into its own gate `#![feature(async_closure)]`.

New tracking issue: rust-lang#62290

Closes rust-lang#62214.

cc rust-lang#62149

r? @varkor
Centril added a commit to Centril/rust that referenced this issue Jul 4, 2019
…mertj

Move `async || ...` closures into `#![feature(async_closure)]`

The `async || expr` syntax is moved out from `#![feature(async_await)]` into its own gate `#![feature(async_closure)]`.

New tracking issue: rust-lang#62290

Closes rust-lang#62214.

cc rust-lang#62149

r? @varkor
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Jul 4, 2019
…mertj

Move `async || ...` closures into `#![feature(async_closure)]`

The `async || expr` syntax is moved out from `#![feature(async_await)]` into its own gate `#![feature(async_closure)]`.

New tracking issue: rust-lang#62290

Closes rust-lang#62214.

cc rust-lang#62149

r? @varkor
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Jul 4, 2019
…mertj

Move `async || ...` closures into `#![feature(async_closure)]`

The `async || expr` syntax is moved out from `#![feature(async_await)]` into its own gate `#![feature(async_closure)]`.

New tracking issue: rust-lang#62290

Closes rust-lang#62214.

cc rust-lang#62149

r? @varkor
Centril added a commit to Centril/rust that referenced this issue Jul 5, 2019
…mertj

Move `async || ...` closures into `#![feature(async_closure)]`

The `async || expr` syntax is moved out from `#![feature(async_await)]` into its own gate `#![feature(async_closure)]`.

New tracking issue: rust-lang#62290

Closes rust-lang#62214.

cc rust-lang#62149

r? @varkor
Centril added a commit to Centril/rust that referenced this issue Jul 5, 2019
…mertj

Move `async || ...` closures into `#![feature(async_closure)]`

The `async || expr` syntax is moved out from `#![feature(async_await)]` into its own gate `#![feature(async_closure)]`.

New tracking issue: rust-lang#62290

Closes rust-lang#62214.

cc rust-lang#62149

r? @varkor
@Centril Centril added F-async_closure `#![feature(async_closure)]` requires-nightly This issue requires a nightly compiler in some way. labels Jul 28, 2019
@khionu
Copy link
Member

khionu commented Sep 28, 2019

Hi, what's the next step for this issue?

@gilescope
Copy link
Contributor

@Centril am bumping into this one quite often in beta... from an ergonomics point of view it would be great to get this stable if there's no outstanding concerns / issues... - is this something we might consider putting 'on-deck', or does it need more settlement time?

@Nemo157
Copy link
Member

Nemo157 commented Oct 6, 2019

Despite "Implement the RFC" being checked this feature is still largely unimplemented (other than the trivial case of async move || {} which is equivalent to move || async move {}), and as far as I'm aware also requires more design work before it can even really be implemented.

@khionu
Copy link
Member

khionu commented Oct 7, 2019

@rustbot modify labels to +AsyncAwait-OnDeck

Closures are a very commonly used language feature, especially in APIs like itertools. Enabling such APIs to be async has obvious benefits.

@Centril
Copy link
Contributor Author

Centril commented Oct 7, 2019

As @Nemo157 points out this is largely unimplemented and is entirely secondary to fixing all the outstanding bugs with the stable part of async/await that we are shipping in 1.39.0.

(Personally I think async closures should be considered holistically with other types of effect-modified closures. Moreover I think they might be largely redundant atop of the combination of closures with async blocks inside them.)

blckngm added a commit to blckngm/titun that referenced this issue Oct 16, 2019
Git rid of async closures. Now `async_closure` is a separate feature
from `async_await` and will be stablized later.

Ref: rust-lang/rust#62290
@CGQAQ
Copy link

CGQAQ commented Nov 29, 2019

Does this will allow ? on Result which have different Error type in the same async closure? currently, there is no way to done that, which is really frustrating

@Nemo157
Copy link
Member

Nemo157 commented Nov 29, 2019

@CGQAQ do you have an example that fails now? Some quick testing in the playground makes it look like inference is able to handle at least simple cases correctly (I definitely could see it being possible that the two layers of generics with inferred outputs might cause some issues for inference, and async closures could potentially improve on that by tying those inferred outputs together somehow).

@mzedeler
Copy link

I am trying to create a helper for tests that are supposed to be run with tokios runtime, so the helper has to be async.

What I want is a function that takes a callback as parameter where the tests can executed, something like:

#[tokio::test]
async fn non_existing_resource() {
    Model::temp(async |model| {
        ...run tests with model here...
    }) // teardown happens in Model::temp()
}

Is there an obvious other way to acheive this?

@Fancyflame
Copy link

If I understand correctly, just replace async || {...} with || async {...}. It acts no differently to async fn.

@sunrosa
Copy link
Contributor

sunrosa commented Jan 16, 2024

So... is this implemented and usable in unstable, or not? I'm seeing it's marked as such, but comments saying otherwise. In what ways is this not implemented?

Also, what are the limitations of the LendingFn solution seen here? It seems like a solid solution, or in the very least, like something that should already exist. But because closures have to implement the trait, the compiler needs to have knowledge of it.

@joebnb

This comment was marked as off-topic.

@kingwingfly
Copy link

If I understand correctly, just replace async || {...} with || async {...}. It acts no differently to async fn.

@Fancyflame
No, you can see this example. It seems the compiler cannot handle the lifetimes correctly without async_closure.

@Fancyflame
Copy link

@kingwingfly Yes, but it's none of the syntax's business, that is because the compiler cannot infer lifetimes inside closure when involving HRTB. And there is a feature solved this problem (I forget the name), I think async_closure just simply uses a part of it. This HRTB problem has been disturbing me for a long time.

Let's do some simplification. Whatever marks you add, the following code cannot pass the compilation.

let _ = |x: &i32| { move || *x };

dcarley added a commit to flox/flox that referenced this issue May 21, 2024
This doesn't work for two reasons..

1. We need to use `async` to read the response body. This could be
solved by restructuring our client code generation so that we put these
functions into the same crate:

    error[E0658]: async closures are unstable
        --> catalog-api-v1/src/client.rs:1654:10
         |
    1654 |         (async |_, result: &reqwest::Result<reqwest::Response>| {
         |          ^^^^^
         |
         = note: see issue #62290 <rust-lang/rust#62290> for more information
         = help: to use an async block, remove the `||`: `async {`

2. Reading a response body takes ownership of the object because the
body is read from the wire and can't be re-read again:

    error[E0507]: cannot move out of `*response` which is behind a shared reference
        --> catalog-api-v1/src/client.rs:1663:36
         |
    1663 |             let mut body_content = response
         |                                    ^^^^^^^^ move occurs because `*response` has type `reqwest::Response`, which does not implement the `Copy` trait
    1664 |                 .text()
         |                  ------ `*response` moved due to this method call
         |
    note: `reqwest::Response::text` takes ownership of the receiver `self`, which moves `*response`
        --> /Users/dcarley/.cargo/registry/src/index.crates.io-6f17d22bba15001f/reqwest-0.11.27/src/async_impl/response.rs:147:23
         |
    147  |     pub async fn text(self) -> crate::Result<String> {
         |                       ^^^^

    error: lifetime may not live long enough
        --> catalog-api-v1/src/client.rs:1658:65
         |
    1658 |           (async |_, result: &reqwest::Result<reqwest::Response>| {
         |  ____________________________-__________________________________-_^
         | |                            |                                  |
         | |                            |                                  return type of closure `{async closure body@catalog-api-v1/src/client.rs:1658:65: 1676:10}` contains a lifetime `'2`
         | |                            let's call the lifetime of this reference `'1`
    1659 | |             let response = result.as_ref().unwrap();
    1660 | |             let status = response.status();
    1661 | |             let url = response.url().clone();
    ...    |
    1675 | |             );
    1676 | |         })(&self.inner, &result);
         | |_________^ returning this value requires that `'1` must outlive `'2`
bors added a commit to rust-lang-ci/rust that referenced this issue Jul 4, 2024
Gauge usage of `FnOnce::Output` in the wild

I'm curious what crates are using `FnOnce::Output` directly. Let's run crater to see.

I downloaded all crates with `get-all-crates --latest` then used `zgrep` to grep for `::Output`, which may or may not be any of the traits in `std::ops`, though it did majorly cut down on the crates we'll crater: https://gist.githubusercontent.com/compiler-errors/1ef63d6e086d9a5915fb510dafdfdd43/raw/86e3bac4235e667c4c2cdf2a21d52ca38567ab1a/gistfile1.txt

With relevance to tracking:

- rust-lang#62290

r? `@ghost`
jhpratt added a commit to jhpratt/rust that referenced this issue Jul 11, 2024
…, r=oli-obk

Implement simple, unstable lint to suggest turning closure-of-async-block into async-closure

We want to eventually suggest people to turn `|| async {}` to `async || {}`. This begins doing that. It's a pretty rudimentary lint, but I wanted to get something down so I wouldn't lose the code.

Tracking:
* rust-lang#62290
bors added a commit to rust-lang-ci/rust that referenced this issue Jul 11, 2024
…r=oli-obk

Implement simple, unstable lint to suggest turning closure-of-async-block into async-closure

We want to eventually suggest people to turn `|| async {}` to `async || {}`. This begins doing that. It's a pretty rudimentary lint, but I wanted to get something down so I wouldn't lose the code.

Tracking:
* rust-lang#62290
@c-git
Copy link

c-git commented Jul 16, 2024

Not sure if this is a suitable place to point to the workaround I use. But this is where the compiler points me every time I bump into this. This post pointed me in the right direction. My main takeaway is put the async on the right of || not the left and then progress becomes possible again (at least for my use cases).

Copy of code so others don't need to follow the link

async fn with_async_callback<Fut: Future<Output = i32>, F: FnOnce() -> Fut>(f: F) -> i32 {
    f().await
}

with_async_closure(|| async { 123 })

Edit

After I'd added my comment I went to re-read the posts and saw the one quoted below that already provided a solution but I didn't find it when I searched because I used the word workaround and possibly others will as well so I decided to leave it.

If I understand correctly, just replace async || {...} with || async {...}. It acts no differently to async fn.

@Fancyflame No, you can see this example. It seems the compiler cannot handle the lifetimes correctly without async_closure.

@traviscross traviscross changed the title Tracking issue for #![feature(async_closure)] (RFC 2394) Tracking issue for #![feature(async_closure)] (RFC 2394) (RFC 3668) Aug 3, 2024
@traviscross traviscross changed the title Tracking issue for #![feature(async_closure)] (RFC 2394) (RFC 3668) Tracking issue for #![feature(async_closure)] (RFC 2394 / RFC 3668) Aug 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await A-closures Area: closures (`|args| { .. }`) AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-RFC-implemented Blocker: Approved by a merged RFC and implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-async_closure `#![feature(async_closure)]` requires-nightly This issue requires a nightly compiler in some way. S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue. WG-async Working group: Async & await
Projects
None yet
Development

No branches or pull requests