Skip to content

Commit

Permalink
Rollup merge of rust-lang#132612 - compiler-errors:async-trait-bounds…
Browse files Browse the repository at this point in the history
…, r=lcnr

Gate async fn trait bound modifier on `async_trait_bounds`

This PR moves `async Fn()` trait bounds into a new feature gate: `feature(async_trait_bounds)`. The general vibe is that we will most likely stabilize the `feature(async_closure)` *without* the `async Fn()` trait bound modifier, so we need to gate that separately.

We're trying to work on the general vision of `async` trait bound modifier general in: rust-lang/rfcs#3710, however that RFC still needs more time for consensus to converge, and we've decided that the value that users get from calling the bound `async Fn()` is *not really* worth blocking landing async closures in general.
  • Loading branch information
matthiaskrgr authored Dec 3, 2024
2 parents 8575f8f + 59e3e89 commit c179a15
Show file tree
Hide file tree
Showing 64 changed files with 147 additions and 106 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
"async closures are unstable",
"to use an async block, remove the `||`: `async {`"
);
gate_all!(
async_trait_bounds,
"`async` trait bounds are unstable",
"use the desugared name of the async trait, such as `AsyncFn`"
);
gate_all!(async_for_loop, "`for await` loops are experimental");
gate_all!(
closure_lifetime_binder,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ declare_features! (
(unstable, async_fn_track_caller, "1.73.0", Some(110011)),
/// Allows `for await` loops.
(unstable, async_for_loop, "1.77.0", Some(118898)),
/// Allows `async` trait bound modifier.
(unstable, async_trait_bounds, "CURRENT_RUSTC_VERSION", Some(62290)),
/// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)),
/// Allows the use of `#[cfg(<true/false>)]`.
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,7 @@ impl<'a> Parser<'a> {
let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
&& self.eat_keyword(kw::Async)
{
self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
BoundAsyncness::Async(self.prev_token.span)
} else if self.may_recover()
&& self.token.uninterpolated_span().is_rust_2015()
Expand All @@ -951,7 +951,7 @@ impl<'a> Parser<'a> {
span: self.prev_token.span,
help: HelpUseLatestEdition::new(),
});
self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
BoundAsyncness::Async(self.prev_token.span)
} else {
BoundAsyncness::Normal
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ symbols! {
async_for_loop,
async_iterator,
async_iterator_poll_next,
async_trait_bounds,
atomic,
atomic_mod,
atomics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
closure_def_id,
found_kind,
expected_kind,
"async ",
"Async",
);
self.note_obligation_cause(&mut err, &obligation);
self.point_at_returns_when_relevant(&mut err, &obligation);
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/pass/async-closure-captures.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync

#![feature(async_closure, noop_waker)]
#![feature(async_closure, noop_waker, async_trait_bounds)]

use std::future::Future;
use std::pin::pin;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/pass/async-closure-drop.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(async_closure, noop_waker, async_fn_traits)]
#![feature(async_closure, noop_waker, async_trait_bounds)]

use std::future::Future;
use std::pin::pin;
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/async-closure-debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#![feature(async_closure)]

fn async_closure_test(upvar: &str) -> impl async Fn() + '_ {
fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ {
async move || {
let hello = String::from("hello");
println!("{hello}, {upvar}");
Expand Down
8 changes: 4 additions & 4 deletions tests/coverage/async_closure.cov-map
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
Function name: async_closure::call_once::<async_closure::main::{closure#0}>
Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c]
Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2b]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44)
- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 43)
Highest counter ID seen: c0

Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0}
Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02]
Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2b, 01, 0e, 05, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14)
- Code(Counter(0)) at (prev + 7, 43) to (start + 1, 14)
- Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2)
Highest counter ID seen: c1

Expand Down
2 changes: 1 addition & 1 deletion tests/coverage/async_closure.coverage
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
LL| |//@ aux-build: executor.rs
LL| |extern crate executor;
LL| |
LL| 1|async fn call_once(f: impl async FnOnce()) {
LL| 1|async fn call_once(f: impl AsyncFnOnce()) {
LL| 1| f().await;
LL| 1|}
LL| |
Expand Down
2 changes: 1 addition & 1 deletion tests/coverage/async_closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//@ aux-build: executor.rs
extern crate executor;

async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/crashes/124020.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ known-bug: #124020
//@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib

#![feature(async_closure, noop_waker, async_fn_traits)]
#![feature(async_closure, noop_waker, async_trait_bounds)]

use std::future::Future;
use std::pin::pin;
Expand All @@ -19,7 +19,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
}
}

async fn call_once(f: impl async FnOnce(DropMe)) {
async fn call_once(f: impl AsyncFnOnce(DropMe)) {
f(DropMe("world")).await;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn main() {
block_on::block_on(async {
let x = async || {};

async fn needs_async_fn_mut(mut x: impl async FnMut()) {
async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) {
x().await;
}
needs_async_fn_mut(x).await;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extern crate block_on;

fn main() {
block_on::block_on(async {
async fn needs_async_fn_once(x: impl async FnOnce()) {
async fn needs_async_fn_once(x: impl AsyncFnOnce()) {
x().await;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/auxiliary/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

#![feature(async_closure)]

pub fn closure() -> impl async Fn() {
pub fn closure() -> impl AsyncFn() {
async || { /* Don't really need to do anything here. */ }
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern crate block_on;

async fn empty() {}

pub async fn call_once<F: async FnOnce()>(f: F) {
pub async fn call_once<F: AsyncFnOnce()>(f: F) {
f().await;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl Trait for (i32,) {
}
}

async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/brand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct S;
struct B<'b>(PhantomData<&'b mut &'b mut ()>);

impl S {
async fn q<F: async Fn(B<'_>)>(self, f: F) {
async fn q<F: AsyncFn(B<'_>)>(self, f: F) {
f(B(PhantomData)).await;
}
}
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/async-await/async-closures/captures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ fn main() {
block_on::block_on(async_main());
}

async fn call<T>(f: &impl async Fn() -> T) -> T {
async fn call<T>(f: &impl AsyncFn() -> T) -> T {
f().await
}

async fn call_once<T>(f: impl async FnOnce() -> T) -> T {
async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
f().await
}

Expand Down Expand Up @@ -80,7 +80,7 @@ async fn async_main() {
call_once(c).await;
}

fn force_fnonce<T>(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T {
fn force_fnonce<T>(f: impl AsyncFnOnce() -> T) -> impl AsyncFnOnce() -> T {
f
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/clone-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

extern crate block_on;

async fn for_each(f: impl async FnOnce(&str) + Clone) {
async fn for_each(f: impl AsyncFnOnce(&str) + Clone) {
f.clone()("world").await;
f.clone()("world2").await;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

#![feature(async_closure)]

fn constrain<T: async FnOnce()>(t: T) -> T {
fn constrain<T: AsyncFnOnce()>(t: T) -> T {
t
}

fn call_once<T>(f: impl FnOnce() -> T) -> T {
f()
}

async fn async_call_once<T>(f: impl async FnOnce() -> T) -> T {
async fn async_call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
f().await
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

extern crate block_on;

async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl Drop for DropMe {
}
}

async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
println!("before call");
let fut = Box::pin(f());
println!("after call");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::future::Future;
#[target_feature(enable = "sse2")]
fn target_feature() -> Pin<Box<dyn Future<Output = ()> + 'static>> { todo!() }

fn test(f: impl async Fn()) {}
fn test(f: impl AsyncFn()) {}

fn main() {
test(target_feature); //~ ERROR the trait bound
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ LL | test(target_feature);
note: required by a bound in `test`
--> $DIR/fn-exception-target-features.rs:13:17
|
LL | fn test(f: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `test`
LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^ required by this bound in `test`

error: aborting due to 1 previous error

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/fn-exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ unsafe extern "C" {
pub safe fn abi() -> Pin<Box<dyn Future<Output = ()> + 'static>>;
}

fn test(f: impl async Fn()) {}
fn test(f: impl AsyncFn()) {}

fn main() {
test(unsafety); //~ ERROR the trait bound
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/async-await/async-closures/fn-exception.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ LL | test(unsafety);
note: required by a bound in `test`
--> $DIR/fn-exception.rs:16:17
|
LL | fn test(f: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `test`
LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^ required by this bound in `test`

error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn()` is not satisfied
--> $DIR/fn-exception.rs:20:10
Expand All @@ -23,8 +23,8 @@ LL | test(abi);
note: required by a bound in `test`
--> $DIR/fn-exception.rs:16:17
|
LL | fn test(f: impl async Fn()) {}
| ^^^^^^^^^^ required by this bound in `test`
LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^ required by this bound in `test`

error: aborting due to 2 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

extern crate block_on;

fn force_fnonce<T: async FnOnce()>(t: T) -> T { t }
fn force_fnonce<T: AsyncFnOnce()>(t: T) -> T { t }

fn main() {
block_on::block_on(async {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extern crate foreign;

struct NoCopy;

async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/implements-fnmut.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ build-pass
//@ edition: 2021

// Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!)
// Demonstrates that an async closure may implement `FnMut` (not just `AsyncFnMut`!)
// if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env,
// since it's fine to reborrow it with its original lifetime. See the doc comment on
// `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/inline-body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
}
}

async fn call_once<T>(f: impl async FnOnce() -> T) -> T {
async fn call_once<T>(f: impl AsyncFnOnce() -> T) -> T {
f().await
}

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/async-await/async-closures/mangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ use std::future::Future;
use std::pin::pin;
use std::task::*;

async fn call_mut(f: &mut impl async FnMut()) {
async fn call_mut(f: &mut impl AsyncFnMut()) {
f().await;
}

async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/moro-example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> {

fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()>
where
for<'scope> B: async FnOnce(&'scope Scope<'scope, 'env>),
for<'scope> B: AsyncFnOnce(&'scope Scope<'scope, 'env>),
{
todo!()
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/move-is-async-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {
is_static(&c);

// Check that `<{async fn} as AsyncFnOnce>::CallOnceFuture` owns its captures.
fn call_once<F: async FnOnce()>(f: F) -> F::CallOnceFuture { f() }
fn call_once<F: AsyncFnOnce()>(f: F) -> F::CallOnceFuture { f() }
is_static(&call_once(c));
});
}
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/mut-ref-reborrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

extern crate block_on;

async fn call_once(f: impl async FnOnce()) { f().await; }
async fn call_once(f: impl AsyncFnOnce()) { f().await; }

pub async fn async_closure(x: &mut i32) {
let c = async move || {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/async-await/async-closures/no-borrow-from-env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

fn outlives<'a>(_: impl Sized + 'a) {}

async fn call_once(f: impl async FnOnce()) {
async fn call_once(f: impl AsyncFnOnce()) {
f().await;
}

Expand Down
Loading

0 comments on commit c179a15

Please sign in to comment.