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) #62290

Open
1 of 3 tasks
Centril opened this issue Jul 2, 2019 · 22 comments
Open
1 of 3 tasks

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

Centril opened this issue Jul 2, 2019 · 22 comments

Comments

@Centril
Copy link
Contributor

@Centril 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:

Unresolved questions:

None as of yet.

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
@khionu
Copy link
Member

@khionu khionu commented Sep 28, 2019

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

@gilescope
Copy link
Contributor

@gilescope gilescope commented Oct 6, 2019

@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 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 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 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.)

sopium added a commit to sopium/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 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 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).

@Centril
Copy link
Contributor Author

@Centril Centril commented Jan 31, 2020

The purpose of this issue to track the development by noting relevant PRs and whatnot as they happen. The feature gate label is also available to route you to relevant places. You can assume that if no recent developments have been noted here, or linked, or provided in the issues with the label, that there are no such developments, so please avoid asking about it here.

@Pzixel
Copy link

@Pzixel Pzixel commented May 10, 2020

Sorry if I missed it, but what's the motivation under this feature? IMO It just adds a slightly different syntax for existing thing (async || vs || async), introducing confusion with no foreseeable benefit. Or at least this is what I see here.

Could you elaborate on that, please?

@khionu
Copy link
Member

@khionu khionu commented May 10, 2020

|| async { } is not an async closure, it's a closure that contains an async block.

@Pzixel
Copy link

@Pzixel Pzixel commented May 10, 2020

Yes, I see it, but what's the difference from the user perspective?

@Nemo157
Copy link
Member

@Nemo157 Nemo157 commented May 10, 2020

There may be differences in how lifetimes in the arguments are treated once they’re supported. Also elaborating the return type is not possible with the closure to async block (playground)

@kaimast
Copy link

@kaimast kaimast commented Nov 24, 2020

Does this feature introduce an AsyncFn trait, similar to core::ops::Fn? I cannot find it in the RFC.

@ibraheemdev
Copy link
Contributor

@ibraheemdev ibraheemdev commented Nov 30, 2020

@kaimast This should become possible once unboxed_closures lands:

#![feature(unboxed_closures, associated_type_bounds, async_closure)]

pub trait AsyncFn<Args>: Fn<Args, Output: core::future::Future<Output = Self::Value>> {
    type Value;
}

impl<F, R, Args> AsyncFn<Args> for F
where
    F: Fn<Args, Output = R>,
    R: core::future::Future,
{
    type Value = R::Output;
}

pub async fn takes_closure<F: AsyncFn<(i32, i32), Value = i32>>(f: F) -> i32 {
    f(23, 32).await
}

fn main() {
    let double = async move |x: i32, y: i32| -> i32 { x * y };
    takes_closure(double);
}

@peepopoggers
Copy link

@peepopoggers peepopoggers commented Oct 16, 2021

What is the progress with async closures? Thanks.

@lnshi
Copy link

@lnshi lnshi commented Oct 23, 2021

Could someone pls explain what are the REAL differences if i do:
1.

let handler = thread::spawn(async || {
    // ....
});

vs 2.

let handler = thread::spawn(|| async {
    // ....
});

vs 3.

let handler = thread::spawn(|| {
    async {
        // ....
    }
});

Currently 1 gives me compiling error directly, i guess there is no difference between 2 and 3?

@seamlik
Copy link

@seamlik seamlik commented Oct 23, 2021

@lnshi

Version 1 is an async closure.

Version 2 and 3 are identical, a normal closure that runs an async block.

@tvallotton
Copy link

@tvallotton tvallotton commented Oct 23, 2021

Aren't async closures just like normal closures but without the redundant move keyword? As in:

move | _ | async move { /* ... */}

vs

async move | _ | { /* ... */ } 

is there any other difference other than this?

@Iron-E
Copy link

@Iron-E Iron-E commented Oct 23, 2021

@Inshi @tvallotton I wrote about a key draw of them in this comment, which should help explain the difference.


In @Inshi's example there is no difference between 2 and 3. You get a compiler error on 1 because it isn't valid syntax yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet