Skip to content

Commit febff99

Browse files
One more caveat about AsyncFn* and built-in impls
1 parent 90ea425 commit febff99

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

text/3668-async-closure.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ let _: Box<dyn async Fn()> = todo!();
276276

277277
All currently-stable callable types (i.e., closures, function items, function pointers, and `dyn Fn*` trait objects) automatically implement `async Fn*() -> T` if they implement `Fn*() -> Fut` for some output type `Fut`, and `Fut` implements `Future<Output = T>`.
278278

279-
This is to make sure that `async Fn*()` trait bounds have maximum compatibility with existing callable types which return futures, such as async function items and closures which return boxed futures. These implementations are built-in, but can conceptually be understood as:
279+
This is to make sure that `async Fn*()` trait bounds have maximum compatibility with existing callable types which return futures, such as async function items and closures which return boxed futures. Async closures also implement `async Fn*()`, but their relationship to this trait is detailed later in the RFC.
280+
281+
These implementations are built-in, but can conceptually be understood as:
280282

281283
```rust
282284
impl<F, Args, Fut, T> AsyncFnOnce<Args> for F
@@ -293,9 +295,11 @@ where
293295
}
294296
```
295297

296-
And similarly for `AsyncFnMut` and `AsyncFn`, with the appropriate `FnMut` and `Fn` trait bounds, respectively.
298+
And similarly for `AsyncFnMut` and `AsyncFn`, with the appropriate `FnMut` and `Fn` trait bounds, respectively.
299+
300+
**NOTE**: This only works currently for *concrete* callable types -- for example, `impl Fn() -> impl Future<Output = ()>` does not implement `impl async Fn()`, due to the fact that these blanket impls do not exist in reality. This may be relaxed in the future. Users can work around this by wrapping their type in an async closure and calling it.
297301

298-
Async closures also implement `async Fn*()`, but their relationship to this trait is detailed later in the RFC. The reason that all of these bounds (for regular callable types *and* async closures) are built-in is because these blanket impls would overlap with the built-in implementation of `AsyncFn*` for async closures, which must have distinct implementations to support self-borrowing futures.
302+
The reason that these implementations are built-in is because using blanket impls would cause overlap with the built-in implementation of `AsyncFn*` for async closures, which must have a distinct implementation to support self-borrowing futures.
299303

300304
Some stable types that implement `async Fn()` today include, e.g.:
301305

0 commit comments

Comments
 (0)