Skip to content

Stabilize async closures (RFC 3668) #132706

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

Merged
merged 2 commits into from
Dec 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -511,11 +511,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
"you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`"
);
gate_all!(let_chains, "`let` expressions in this position are unstable");
gate_all!(
async_closure,
"async closures are unstable",
"to use an async block, remove the `||`: `async {`"
);
gate_all!(
async_trait_bounds,
"`async` trait bounds are unstable",
4 changes: 0 additions & 4 deletions compiler/rustc_error_codes/src/error_codes/E0708.md
Original file line number Diff line number Diff line change
@@ -5,8 +5,6 @@
Erroneous code example:

```edition2018
#![feature(async_closure)]

fn main() {
let add_one = async |num: u8| {
num + 1
@@ -18,8 +16,6 @@ fn main() {
version, you can use successfully by using move:

```edition2018
#![feature(async_closure)]

fn main() {
let add_one = async move |num: u8| { // ok!
num + 1
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
@@ -72,6 +72,8 @@ declare_features! (
(accepted, associated_types, "1.0.0", None),
/// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions.
(accepted, async_await, "1.39.0", Some(50547)),
/// Allows `async || body` closures.
(accepted, async_closure, "CURRENT_RUSTC_VERSION", Some(62290)),
/// Allows async functions to be declared, implemented, and used in traits.
(accepted, async_fn_in_trait, "1.75.0", Some(91611)),
/// Allows all literals in attribute lists and values of key-value pairs.
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
@@ -388,8 +388,6 @@ declare_features! (
(unstable, associated_const_equality, "1.58.0", Some(92827)),
/// Allows associated type defaults.
(unstable, associated_type_defaults, "1.2.0", Some(29661)),
/// Allows `async || body` closures.
(unstable, async_closure, "1.37.0", Some(62290)),
/// Allows async functions to be called from `dyn Trait`.
(incomplete, async_fn_in_dyn_trait, "CURRENT_RUSTC_VERSION", Some(133119)),
/// Allows `#[track_caller]` on async functions.
2 changes: 0 additions & 2 deletions compiler/rustc_hir_typeck/src/upvar.rs
Original file line number Diff line number Diff line change
@@ -1840,7 +1840,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// captured by move.
///
/// ```rust
/// #![feature(async_closure)]
/// let x = &1i32; // Let's call this lifetime `'1`.
/// let c = async move || {
/// println!("{:?}", *x);
@@ -1855,7 +1854,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// child capture with the lifetime of the parent coroutine-closure's env.
///
/// ```rust
/// #![feature(async_closure)]
/// let mut x = 1i32;
/// let c = async || {
/// x = 1;
4 changes: 0 additions & 4 deletions compiler/rustc_lint/src/async_closures.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ declare_lint! {
/// ### Example
///
/// ```rust
/// #![feature(async_closure)]
/// #![warn(closure_returning_async_block)]
/// let c = |x: &str| async {};
/// ```
@@ -40,8 +39,6 @@ declare_lint! {
/// But it does work with async closures:
///
/// ```rust
/// #![feature(async_closure)]
///
/// async fn callback(x: &str) {}
///
/// let captured_str = String::new();
@@ -52,7 +49,6 @@ declare_lint! {
pub CLOSURE_RETURNING_ASYNC_BLOCK,
Allow,
"closure that returns `async {}` could be rewritten as an async closure",
@feature_gate = async_closure;
}

declare_lint_pass!(
2 changes: 0 additions & 2 deletions compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
Original file line number Diff line number Diff line change
@@ -3,8 +3,6 @@
//!
//! Consider an async closure like:
//! ```rust
//! #![feature(async_closure)]
//!
//! let x = vec![1, 2, 3];
//!
//! let closure = async move || {
5 changes: 1 addition & 4 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
@@ -2366,10 +2366,7 @@ impl<'a> Parser<'a> {
};

match coroutine_kind {
Some(CoroutineKind::Async { span, .. }) => {
// Feature-gate `async ||` closures.
self.psess.gated_spans.gate(sym::async_closure, span);
}
Some(CoroutineKind::Async { .. }) => {}
Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
// Feature-gate `gen ||` and `async gen ||` closures.
// FIXME(gen_blocks): This perhaps should be a different gate.
9 changes: 6 additions & 3 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
@@ -1985,7 +1985,8 @@ impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
}
}

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<Args: Tuple, F: AsyncFnOnce<Args> + ?Sized, A: Allocator> AsyncFnOnce<Args> for Box<F, A> {
type Output = F::Output;
type CallOnceFuture = F::CallOnceFuture;
@@ -1995,7 +1996,8 @@ impl<Args: Tuple, F: AsyncFnOnce<Args> + ?Sized, A: Allocator> AsyncFnOnce<Args>
}
}

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<Args: Tuple, F: AsyncFnMut<Args> + ?Sized, A: Allocator> AsyncFnMut<Args> for Box<F, A> {
type CallRefFuture<'a>
= F::CallRefFuture<'a>
@@ -2007,7 +2009,8 @@ impl<Args: Tuple, F: AsyncFnMut<Args> + ?Sized, A: Allocator> AsyncFnMut<Args> f
}
}

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<Args: Tuple, F: AsyncFn<Args> + ?Sized, A: Allocator> AsyncFn<Args> for Box<F, A> {
extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> {
F::async_call(self, args)
2 changes: 1 addition & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -91,6 +91,7 @@
//
// Library features:
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(async_closure))]
#![cfg_attr(test, feature(str_as_str))]
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
@@ -99,7 +100,6 @@
#![feature(array_windows)]
#![feature(ascii_char)]
#![feature(assert_matches)]
#![feature(async_closure)]
#![feature(async_fn_traits)]
#![feature(async_iterator)]
#![feature(box_uninit_write)]
24 changes: 16 additions & 8 deletions library/core/src/ops/async_function.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,8 @@ use crate::marker::Tuple;
/// An async-aware version of the [`Fn`](crate::ops::Fn) trait.
///
/// All `async fn` and functions returning futures implement this trait.
#[unstable(feature = "async_closure", issue = "62290")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
#[rustc_paren_sugar]
#[fundamental]
#[must_use = "async closures are lazy and do nothing unless called"]
@@ -18,7 +19,8 @@ pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> {
/// An async-aware version of the [`FnMut`](crate::ops::FnMut) trait.
///
/// All `async fn` and functions returning futures implement this trait.
#[unstable(feature = "async_closure", issue = "62290")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
#[rustc_paren_sugar]
#[fundamental]
#[must_use = "async closures are lazy and do nothing unless called"]
@@ -39,7 +41,8 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> {
/// An async-aware version of the [`FnOnce`](crate::ops::FnOnce) trait.
///
/// All `async fn` and functions returning futures implement this trait.
#[unstable(feature = "async_closure", issue = "62290")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
#[rustc_paren_sugar]
#[fundamental]
#[must_use = "async closures are lazy and do nothing unless called"]
@@ -64,7 +67,8 @@ mod impls {
use super::{AsyncFn, AsyncFnMut, AsyncFnOnce};
use crate::marker::Tuple;

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<A: Tuple, F: ?Sized> AsyncFn<A> for &F
where
F: AsyncFn<A>,
@@ -74,7 +78,8 @@ mod impls {
}
}

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &F
where
F: AsyncFn<A>,
@@ -89,7 +94,8 @@ mod impls {
}
}

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a F
where
F: AsyncFn<A>,
@@ -102,7 +108,8 @@ mod impls {
}
}

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<A: Tuple, F: ?Sized> AsyncFnMut<A> for &mut F
where
F: AsyncFnMut<A>,
@@ -117,7 +124,8 @@ mod impls {
}
}

#[unstable(feature = "async_fn_traits", issue = "none")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
impl<'a, A: Tuple, F: ?Sized> AsyncFnOnce<A> for &'a mut F
where
F: AsyncFnMut<A>,
3 changes: 2 additions & 1 deletion library/std/src/prelude/common.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,8 @@ pub use crate::marker::{Send, Sized, Sync, Unpin};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
#[unstable(feature = "async_closure", issue = "62290")]
#[cfg_attr(bootstrap, unstable(feature = "async_closure", issue = "62290"))]
#[cfg_attr(not(bootstrap), stable(feature = "async_closure", since = "CURRENT_RUSTC_VERSION"))]
#[doc(no_inline)]
pub use crate::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};

5 changes: 3 additions & 2 deletions library/std/src/prelude/mod.rs
Original file line number Diff line number Diff line change
@@ -33,8 +33,9 @@
//!
//! * <code>[std::marker]::{[Copy], [Send], [Sized], [Sync], [Unpin]}</code>,
//! marker traits that indicate fundamental properties of types.
//! * <code>[std::ops]::{[Drop], [Fn], [FnMut], [FnOnce]}</code>, various
//! operations for both destructors and overloading `()`.
//! * <code>[std::ops]::{[Fn], [FnMut], [FnOnce]}</code>, and their analogous
//! async traits, <code>[std::ops]::{[AsyncFn], [AsyncFnMut], [AsyncFnOnce]}</code>.
//! * <code>[std::ops]::[Drop]</code>, for implementing destructors.
//! * <code>[std::mem]::[drop]</code>, a convenience function for explicitly
//! dropping a value.
//! * <code>[std::mem]::{[size_of], [size_of_val]}</code>, to get the size of
1 change: 0 additions & 1 deletion src/tools/clippy/tests/ui/async_yields_async.fixed
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
#![allow(clippy::redundant_async_block)]

1 change: 0 additions & 1 deletion src/tools/clippy/tests/ui/async_yields_async.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
#![allow(clippy::redundant_async_block)]

12 changes: 6 additions & 6 deletions src/tools/clippy/tests/ui/async_yields_async.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:38:9
--> tests/ui/async_yields_async.rs:37:9
|
LL | let _h = async {
| _____________________-
@@ -20,7 +20,7 @@ LL + }.await
|

error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:43:9
--> tests/ui/async_yields_async.rs:42:9
|
LL | let _i = async {
| ____________________-
@@ -33,7 +33,7 @@ LL | | };
| |_____- outer async construct

error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:49:9
--> tests/ui/async_yields_async.rs:48:9
|
LL | let _j = async || {
| ________________________-
@@ -52,7 +52,7 @@ LL + }.await
|

error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:54:9
--> tests/ui/async_yields_async.rs:53:9
|
LL | let _k = async || {
| _______________________-
@@ -65,7 +65,7 @@ LL | | };
| |_____- outer async construct

error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:56:23
--> tests/ui/async_yields_async.rs:55:23
|
LL | let _l = async || CustomFutureType;
| ^^^^^^^^^^^^^^^^
@@ -75,7 +75,7 @@ LL | let _l = async || CustomFutureType;
| help: consider awaiting this value: `CustomFutureType.await`

error: an async construct yields a type which is itself awaitable
--> tests/ui/async_yields_async.rs:62:9
--> tests/ui/async_yields_async.rs:61:9
|
LL | let _m = async || {
| _______________________-
1 change: 0 additions & 1 deletion src/tools/clippy/tests/ui/author/blocks.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@

#![allow(redundant_semicolons, clippy::no_effect)]
#![feature(stmt_expr_attributes)]
#![feature(async_closure)]

#[rustfmt::skip]
fn main() {
1 change: 0 additions & 1 deletion src/tools/clippy/tests/ui/infinite_loops.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@

#![allow(clippy::never_loop)]
#![warn(clippy::infinite_loop)]
#![feature(async_closure)]

extern crate proc_macros;
use proc_macros::{external, with_span};
Loading