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
Copy file name to clipboardExpand all lines: posts/inside-rust/2024-08-09-async-closures-call-for-testing.md
+12-12Lines changed: 12 additions & 12 deletions
Original file line number
Diff line number
Diff line change
@@ -5,20 +5,20 @@ author: Michael Goulet
5
5
team: The Async Working Group <https://www.rust-lang.org/governance/wgs/wg-async>
6
6
---
7
7
8
-
The async working group is excited to announce that [RFC 3668] "Async Closures" was recently approved by the Lang team. In this post, we want to briefly motivate why they exist, explain their current shortcomings, and most importantly, announce a call for testing them on nightly Rust.
8
+
The async working group is excited to announce that [RFC 3668] "Async Closures" was recently approved by the Lang team. In this post, we want to briefly motivate why async closures exist, explain their current shortcomings, and most importantly, announce a call for testing them on nightly Rust.
9
9
10
10
## The backstory
11
11
12
-
Async closures were originally proposed in [RFC 2394](https://rust-lang.github.io/rfcs/2394-async_await.html#async--closures) which introduced `async`/`await` to the language. Simple handling of async closures has existed since async-await was implemented [soon thereafter](https://github.com/rust-lang/rust/pull/51580), but until recently async closures simply desugared into closures that returned async blocks:
12
+
Async closures were originally proposed in [RFC 2394](https://rust-lang.github.io/rfcs/2394-async_await.html#async--closures) which introduced `async`/`await` to the language. Simple handling of async closures has existed in nightly since async-await was implemented [soon thereafter](https://github.com/rust-lang/rust/pull/51580), but until recently async closures simply desugared into closures that returned async blocks:
13
13
14
14
```rust
15
15
letx=async|| {};
16
16
17
-
// ...is just sugar for:
17
+
// ...was just sugar for:
18
18
letx=|| { async {} };
19
19
```
20
20
21
-
This had a fundamental limitation that it's impossible to express a closure that returns a future that borrows captured state.
21
+
This had a fundamental limitation that it was impossible to express a closure that returns a future that borrows captured state.
22
22
23
23
Somewhat relatedly, on the callee side, when users want to take an async closure as an argument, they must express that as a bound of two different generic types, or use boxing:
24
24
@@ -34,13 +34,13 @@ where
34
34
F:FnOnce() ->Pin<Box<dynFuture<Output=String>>>;
35
35
```
36
36
37
-
This led to an additional limitation, that it's impossible to express higherranked async fn bounds without boxing, since a higherranked trait bound on `F` cannot lead to a higher-ranked type for `Fut`.
37
+
This led to an additional limitation, that it's impossible to express higher-ranked async fn bounds without boxing, since a higher-ranked trait bound on `F` cannot lead to a higher-ranked type for `Fut`.
38
38
39
39
These limitations were detailed in [Niko's blog post on async closures and lending](https://smallcultfollowing.com/babysteps/blog/2023/05/09/giving-lending-and-async-closures/#async-closures-are-a-lending-pattern), and later in compiler-errors's blog post on [why async closures are the way they are](https://hackmd.io/@compiler-errors/async-closures).
40
40
41
41
## OK, so how does [RFC 3668] help?
42
42
43
-
Recent [implementation work](https://github.com/rust-lang/rust/pull/120361) has focused on reimplementing async closures to be lending, and to design a set of async fn traits to use in parallel. While async closures already existed as syntax, it introduced a new family of async fn traits which are implemented by async closures (and all other callable types which return futures), and which can be written like:
43
+
Recent [work](https://github.com/rust-lang/rust/pull/120361) has focused on reimplementing async closures to be lending and designing a set of async fn traits. While async closures already existed as syntax, this work introduced a new family of async fn traits which are implemented by async closures (and all other callable types which return futures). They can be written like:
44
44
45
45
```rust
46
46
fntest<F>(callback:F)
@@ -57,9 +57,9 @@ RFC 3668 motivates this implementation work in detail, confirming that we need f
## Shortcomings interacting with the async ecosystem
93
93
94
-
If you're going to try to rewrite your async projects, there are a few shortcomings you may want to be aware of.
94
+
If you're going to try to rewrite your async projects, there are a few shortcomings to be aware of.
95
95
96
96
### You can't directly name the output future
97
97
@@ -113,12 +113,12 @@ We expect to support this in the medium/long term via a [return-type-notation sy
113
113
114
114
Passing an async closure to a generic `impl Fn(A, B) -> C` bound may not always eagerly infer the closure's arguments to `A` and `B`, leading to strange type errors on occasion. For an example of this, see [`rust-lang/rust#127781`](https://github.com/rust-lang/rust/issues/127781).
115
115
116
-
We expect to improve async closure signature inference moving forward.
116
+
We expect to improve async closure signature inference as we move forward.
117
117
118
118
### Async closures can't be coerced to `fn()` pointers
119
119
120
120
Some libraries take their callbacks as function *pointers* (`fn()`) rather than generics. Async closures don't currently implement the same coercion from closure to `fn() -> ...`. Some libraries may mitigate this problem by adapting their API to take generic `impl Fn()` instead of `fn()` pointers as an argument.
121
121
122
-
We don't expect to implement this coercion unless there's a particularly good reason to support, since they can always be replaced with an inner function item.
122
+
We don't expect to implement this coercion unless there's a particularly good reason to support it, since this can always be handled manually by the caller with an inner function item.
0 commit comments