diff --git a/mdbook-spec/src/std_links.rs b/mdbook-spec/src/std_links.rs
index 28ca6ba51..e5b9448d1 100644
--- a/mdbook-spec/src/std_links.rs
+++ b/mdbook-spec/src/std_links.rs
@@ -247,7 +247,7 @@ fn run_rustdoc(tmp: &TempDir, chapter_links: &HashMap<&PathBuf, Vec>>)
fs::write(&src_path, &src).unwrap();
let rustdoc = std::env::var("RUSTDOC").unwrap_or_else(|_| "rustdoc".into());
let output = Command::new(rustdoc)
- .arg("--edition=2021")
+ .arg("--edition=2024")
.arg(&src_path)
.current_dir(tmp.path())
.output()
diff --git a/src/expressions/await-expr.md b/src/expressions/await-expr.md
index ae129890f..2d233f348 100644
--- a/src/expressions/await-expr.md
+++ b/src/expressions/await-expr.md
@@ -8,7 +8,7 @@ An `await` expression is a syntactic construct for suspending a computation
provided by an implementation of `std::future::IntoFuture` until the given
future is ready to produce a value.
The syntax for an await expression is an expression with a type that implements the [`IntoFuture`] trait, called the *future operand*, then the token `.`, and then the `await` keyword.
-Await expressions are legal only within an [async context], like an [`async fn`] or an [`async` block].
+Await expressions are legal only within an [async context], like an [`async fn`], [`async` closure], or [`async` block].
More specifically, an await expression has the following effect.
@@ -48,6 +48,7 @@ The variable `current_context` refers to the context taken from the async enviro
[_Expression_]: ../expressions.md
[`async fn`]: ../items/functions.md#async-functions
+[`async` closure]: closure-expr.md#async-closures
[`async` block]: block-expr.md#async-blocks
[`Context`]: std::task::Context
[`future::poll`]: std::future::Future::poll
diff --git a/src/expressions/call-expr.md b/src/expressions/call-expr.md
index 64df58ce4..fc196b7a6 100644
--- a/src/expressions/call-expr.md
+++ b/src/expressions/call-expr.md
@@ -10,7 +10,13 @@
A *call expression* calls a function.
The syntax of a call expression is an expression, called the *function operand*, followed by a parenthesized comma-separated list of expression, called the *argument operands*.
If the function eventually returns, then the expression completes.
-For [non-function types], the expression `f(...)` uses the method on one of the [`std::ops::Fn`], [`std::ops::FnMut`] or [`std::ops::FnOnce`] traits, which differ in whether they take the type by reference, mutable reference, or take ownership respectively.
+
+For [non-function types], the expression `f(...)` uses the method on one of the following traits based on the function operand:
+
+- [`Fn`] or [`AsyncFn`] --- shared reference.
+- [`FnMut`] or [`AsyncFnMut`] --- mutable reference.
+- [`FnOnce`] or [`AsyncFnOnce`] --- value.
+
An automatic borrow will be taken if needed.
The function operand will also be [automatically dereferenced] as required.
diff --git a/src/expressions/closure-expr.md b/src/expressions/closure-expr.md
index 103f74795..abb3c8e9a 100644
--- a/src/expressions/closure-expr.md
+++ b/src/expressions/closure-expr.md
@@ -2,6 +2,7 @@
> **Syntax**\
> _ClosureExpression_ :\
+> `async`[^cl-async-edition]?\
> `move`?\
> ( `||` | `|` _ClosureParameters_? `|` )\
> ([_Expression_] | `->` [_TypeNoBounds_] [_BlockExpression_])
@@ -11,9 +12,11 @@
>
> _ClosureParam_ :\
> [_OuterAttribute_]\* [_PatternNoTopAlt_] ( `:` [_Type_] )?
+>
+> [^cl-async-edition]: The `async` qualifier is not allowed in the 2015 edition.
A *closure expression*, also known as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type.
-The syntax for a closure expression is an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], called the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, called the *return type*, and then an expression, called the *closure body operand*.
+The syntax for a closure expression is an optional `async` keyword, an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], called the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, called the *return type*, and then an expression, called the *closure body operand*.
The optional type after each pattern is a type annotation for the pattern.
If there is a return type, the closure body must be a [block].
@@ -29,10 +32,32 @@ This is often used to ensure that the closure's lifetime is `'static`.
## Closure trait implementations
-Which traits the closure type implement depends on how variables are captured and the types of the captured variables.
+Which traits the closure type implement depends on how variables are captured, the types of the captured variables, and the presence of `async`.
See the [call traits and coercions] chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`.
The closure type implements [`Send`] and [`Sync`] if the type of every captured variable also implements the trait.
+## Async closures
+
+Closures marked with the `async` keyword indicate that they are asynchronous in an analogous way to an [async function][items.fn.async].
+
+Calling the async closure does not perform any work, but instead evaluates to a value that implements [`Future`] that corresponds to the computation of the body of the closure.
+
+```rust
+async fn takes_async_callback(f: impl AsyncFn(u64)) {
+ f(0).await;
+ f(1).await;
+}
+
+async fn example() {
+ takes_async_callback(async |i| {
+ core::future::ready(i).await;
+ println!("done with {i}.");
+ }).await;
+}
+```
+
+> **Edition differences**: Async closures are only available beginning with Rust 2018.
+
## Example
In this example, we define a function `ten_times` that takes a higher-order function argument, and we then call it with a closure expression as an argument, followed by a closure expression that moves values from its environment.
diff --git a/src/items/traits.md b/src/items/traits.md
index dd315e440..0d0a9ecbd 100644
--- a/src/items/traits.md
+++ b/src/items/traits.md
@@ -120,6 +120,9 @@ r[items.traits.dyn-compatible.associated-functions]
* Explicitly non-dispatchable functions require:
* Have a `where Self: Sized` bound (receiver type of `Self` (i.e. `self`) implies this).
+r[items.traits.dyn-compatible.async-traits]
+* The [`AsyncFn`], [`AsyncFnMut`], and [`AsyncFnOnce`] traits are not dyn-compatible.
+
> **Note**: This concept was formerly known as *object safety*.
```rust
diff --git a/src/types/closure.md b/src/types/closure.md
index d46d7f7ae..2fc59276d 100644
--- a/src/types/closure.md
+++ b/src/types/closure.md
@@ -94,6 +94,11 @@ let c = || {
};
```
+### Async input capture
+
+r[type.closure.async.input]
+Async closures always capture all input arguments, regardless of whether or not they are used within the body.
+
## Capture Precision
r[type.closure.capture.precision.capture-path]
@@ -491,7 +496,7 @@ r[type.closure.call.fn]
r[type.closure.non-capturing]
*Non-capturing closures* are closures that don't capture anything from their
-environment. They can be coerced to function pointers (e.g., `fn()`)
+environment. Non-async, non-capturing closures can be coerced to function pointers (e.g., `fn()`)
with the matching signature.
```rust
@@ -504,7 +509,66 @@ let bo: Binop = add;
x = bo(5,7);
```
-## Other traits
+### Async closure traits
+
+r[type.closure.async.traits]
+
+r[type.closure.async.traits.fn-family]
+Async closures have a further restriction of whether or not they implement [`FnMut`] or [`Fn`].
+
+The [`Future`] returned by the async closure has similar capturing characteristics as a closure. It captures place expressions from the async closure based on how they are used. The async closure is said to be *lending* to its [`Future`] if it has either of the following properties:
+
+- The `Future` includes a mutable capture.
+- The async closure captures by value, except when the value is accessed with a dereference projection.
+
+If the async closure is lending to its `Future`, then [`FnMut`] and [`Fn`] are *not* implemented. [`FnOnce`] is always implemented.
+
+> **Example**: The first clause for a mutable capture can be illustrated with the following:
+>
+> ```rust,compile_fail
+> fn takes_callback(c: impl FnMut() -> Fut) {}
+>
+> fn f() {
+> let mut x = 1i32;
+> let c = async || {
+> x = 2; // x captured with MutBorrow
+> };
+> takes_callback(c); // ERROR: async closure does not implement `FnMut`
+> }
+> ```
+>
+> The second clause for a regular value capture can be illustrated with the following:
+>
+> ```rust,compile_fail
+> fn takes_callback(c: impl Fn() -> Fut) {}
+>
+> fn f() {
+> let x = &1i32;
+> let c = async move || {
+> let a = x + 2; // x captured ByValue
+> };
+> takes_callback(c); // ERROR: async closure does not implement `Fn`
+> }
+> ```
+>
+> The exception of the the second clause can be illustrated by using a dereference, which does allow `Fn` and `FnMut` to be implemented:
+>
+> ```rust
+> fn takes_callback(c: impl Fn() -> Fut) {}
+>
+> fn f() {
+> let x = &1i32;
+> let c = async move || {
+> let a = *x + 2;
+> };
+> takes_callback(c); // OK: implements `Fn`
+> }
+> ```
+
+r[type.closure.async.traits.async-family]
+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.
+
+### Other traits
r[type.closure.traits]
diff --git a/src/types/function-pointer.md b/src/types/function-pointer.md
index d7950b159..21a398265 100644
--- a/src/types/function-pointer.md
+++ b/src/types/function-pointer.md
@@ -31,7 +31,7 @@ Function pointer types, written using the `fn` keyword, refer to a function
whose identity is not necessarily known at compile-time.
r[type.fn-pointer.coercion]
-They can be created via a coercion from both [function items] and non-capturing [closures].
+They can be created via a coercion from both [function items] and non-capturing, non-async [closures].
r[type.fn-pointer.qualifiers]
The `unsafe` qualifier indicates that the type's value is an [unsafe