Skip to content

Commit 5a8b949

Browse files
committed
Add examples for async's Fn* rules
These are pretty subtle, and hard to follow. An example helps a lot. I really wanted to include a little bit more commentary on *why* these apply, but I think that gets into some fairly complicated reasoning that I'm not prepared to distill.
1 parent adef05f commit 5a8b949

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

src/types/closure.md

+42
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,48 @@ The [`Future`] returned by the async closure has similar capturing characteristi
523523

524524
If the async closure is lending to its `Future`, then [`FnMut`] and [`Fn`] are *not* implemented.
525525

526+
> **Example**: The first clause for a mutable capture can be illustrated with the following:
527+
>
528+
> ```rust,compile_fail
529+
> fn takes_callback<Fut: Future>(c: impl FnMut() -> Fut) {}
530+
>
531+
> fn f() {
532+
> let mut x = 1i32;
533+
> let c = async || {
534+
> x = 2; // x captured with MutBorrow
535+
> };
536+
> takes_callback(c); // ERROR: async closure does not implement `FnMut`
537+
> }
538+
> ```
539+
>
540+
> The second clause for a regular value capture can be illustrated with the following:
541+
>
542+
> ```rust,compile_fail
543+
> fn takes_callback<Fut: Future>(c: impl Fn() -> Fut) {}
544+
>
545+
> fn f() {
546+
> let x = &1i32;
547+
> let c = async move || {
548+
> let a = x + 2; // x captured ByValue
549+
> };
550+
> takes_callback(c); // ERROR: async closure does not implement `Fn`
551+
> }
552+
> ```
553+
>
554+
> The exception of the the second clause can be illustrated by using a dereference, which does allow `Fn` and `FnMut` to be implemented:
555+
>
556+
> ```rust
557+
> fn takes_callback<Fut: Future>(c: impl Fn() -> Fut) {}
558+
>
559+
> fn f() {
560+
> let x = &1i32;
561+
> let c = async move || {
562+
> let a = *x + 2;
563+
> };
564+
> takes_callback(c); // OK: implements `Fn`
565+
> }
566+
> ```
567+
526568
r[type.closure.async.traits.async-family]
527569
Async closures implement [`AsyncFn`], [`AsyncFnMut`], and [`AsyncFnOnce`] in an analogous way as regular closures implement [`Fn`], [`FnMut`], and [`FnOnce`]; that is, depending on the use of the captured variables in its body.
528570

0 commit comments

Comments
 (0)