1
Fork 0

Rollup merge of #132612 - compiler-errors:async-trait-bounds, 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: https://github.com/rust-lang/rfcs/pull/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.
This commit is contained in:
Matthias Krüger 2024-12-03 17:27:05 +01:00 committed by GitHub
commit c179a15f7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
64 changed files with 147 additions and 106 deletions

View file

@ -516,6 +516,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
"async closures are unstable", "async closures are unstable",
"to use an async block, remove the `||`: `async {`" "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!(async_for_loop, "`for await` loops are experimental");
gate_all!( gate_all!(
closure_lifetime_binder, closure_lifetime_binder,

View file

@ -394,6 +394,8 @@ declare_features! (
(unstable, async_fn_track_caller, "1.73.0", Some(110011)), (unstable, async_fn_track_caller, "1.73.0", Some(110011)),
/// Allows `for await` loops. /// Allows `for await` loops.
(unstable, async_for_loop, "1.77.0", Some(118898)), (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. /// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)), (unstable, c_variadic, "1.34.0", Some(44930)),
/// Allows the use of `#[cfg(<true/false>)]`. /// Allows the use of `#[cfg(<true/false>)]`.

View file

@ -940,7 +940,7 @@ impl<'a> Parser<'a> {
let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
&& self.eat_keyword(kw::Async) && 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) BoundAsyncness::Async(self.prev_token.span)
} else if self.may_recover() } else if self.may_recover()
&& self.token.uninterpolated_span().is_rust_2015() && self.token.uninterpolated_span().is_rust_2015()
@ -951,7 +951,7 @@ impl<'a> Parser<'a> {
span: self.prev_token.span, span: self.prev_token.span,
help: HelpUseLatestEdition::new(), 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) BoundAsyncness::Async(self.prev_token.span)
} else { } else {
BoundAsyncness::Normal BoundAsyncness::Normal

View file

@ -468,6 +468,7 @@ symbols! {
async_for_loop, async_for_loop,
async_iterator, async_iterator,
async_iterator_poll_next, async_iterator_poll_next,
async_trait_bounds,
atomic, atomic,
atomic_mod, atomic_mod,
atomics, atomics,

View file

@ -794,7 +794,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
closure_def_id, closure_def_id,
found_kind, found_kind,
expected_kind, expected_kind,
"async ", "Async",
); );
self.note_obligation_cause(&mut err, &obligation); self.note_obligation_cause(&mut err, &obligation);
self.point_at_returns_when_relevant(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation);

View file

@ -1,6 +1,6 @@
// Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync // 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::future::Future;
use std::pin::pin; use std::pin::pin;

View file

@ -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::future::Future;
use std::pin::pin; use std::pin::pin;

View file

@ -9,7 +9,7 @@
#![feature(async_closure)] #![feature(async_closure)]
fn async_closure_test(upvar: &str) -> impl async Fn() + '_ { fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ {
async move || { async move || {
let hello = String::from("hello"); let hello = String::from("hello");
println!("{hello}, {upvar}"); println!("{hello}, {upvar}");

View file

@ -1,19 +1,19 @@
Function name: async_closure::call_once::<async_closure::main::{closure#0}> 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 Number of files: 1
- file 0 => global file 1 - file 0 => global file 1
Number of expressions: 0 Number of expressions: 0
Number of file 0 mappings: 1 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 Highest counter ID seen: c0
Function name: async_closure::call_once::<async_closure::main::{closure#0}>::{closure#0} 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 Number of files: 1
- file 0 => global file 1 - file 0 => global file 1
Number of expressions: 0 Number of expressions: 0
Number of file 0 mappings: 2 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) - Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2)
Highest counter ID seen: c1 Highest counter ID seen: c1

View file

@ -4,7 +4,7 @@
LL| |//@ aux-build: executor.rs LL| |//@ aux-build: executor.rs
LL| |extern crate executor; LL| |extern crate executor;
LL| | 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| f().await;
LL| 1|} LL| 1|}
LL| | LL| |

View file

@ -4,7 +4,7 @@
//@ aux-build: executor.rs //@ aux-build: executor.rs
extern crate executor; extern crate executor;
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await; f().await;
} }

View file

@ -1,7 +1,7 @@
//@ known-bug: #124020 //@ known-bug: #124020
//@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib //@ 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::future::Future;
use std::pin::pin; use std::pin::pin;
@ -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; f(DropMe("world")).await;
} }

View file

@ -10,7 +10,7 @@ fn main() {
block_on::block_on(async { block_on::block_on(async {
let x = 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; x().await;
} }
needs_async_fn_mut(x).await; needs_async_fn_mut(x).await;

View file

@ -8,7 +8,7 @@ extern crate block_on;
fn main() { fn main() {
block_on::block_on(async { 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; x().await;
} }

View file

@ -2,6 +2,6 @@
#![feature(async_closure)] #![feature(async_closure)]
pub fn closure() -> impl async Fn() { pub fn closure() -> impl AsyncFn() {
async || { /* Don't really need to do anything here. */ } async || { /* Don't really need to do anything here. */ }
} }

View file

@ -11,7 +11,7 @@ extern crate block_on;
async fn empty() {} async fn empty() {}
pub async fn call_once<F: async FnOnce()>(f: F) { pub async fn call_once<F: AsyncFnOnce()>(f: F) {
f().await; f().await;
} }

View file

@ -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; f().await;
} }

View file

@ -13,7 +13,7 @@ struct S;
struct B<'b>(PhantomData<&'b mut &'b mut ()>); struct B<'b>(PhantomData<&'b mut &'b mut ()>);
impl S { 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; f(B(PhantomData)).await;
} }
} }

View file

@ -13,11 +13,11 @@ fn main() {
block_on::block_on(async_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 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 f().await
} }
@ -80,7 +80,7 @@ async fn async_main() {
call_once(c).await; 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 f
} }

View file

@ -7,7 +7,7 @@
extern crate block_on; 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()("world").await;
f.clone()("world2").await; f.clone()("world2").await;
} }

View file

@ -6,7 +6,7 @@
#![feature(async_closure)] #![feature(async_closure)]
fn constrain<T: async FnOnce()>(t: T) -> T { fn constrain<T: AsyncFnOnce()>(t: T) -> T {
t t
} }
@ -14,7 +14,7 @@ fn call_once<T>(f: impl FnOnce() -> T) -> T {
f() 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 f().await
} }

View file

@ -7,7 +7,7 @@
extern crate block_on; extern crate block_on;
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await; f().await;
} }

View file

@ -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"); println!("before call");
let fut = Box::pin(f()); let fut = Box::pin(f());
println!("after call"); println!("after call");

View file

@ -10,7 +10,7 @@ use std::future::Future;
#[target_feature(enable = "sse2")] #[target_feature(enable = "sse2")]
fn target_feature() -> Pin<Box<dyn Future<Output = ()> + 'static>> { todo!() } fn target_feature() -> Pin<Box<dyn Future<Output = ()> + 'static>> { todo!() }
fn test(f: impl async Fn()) {} fn test(f: impl AsyncFn()) {}
fn main() { fn main() {
test(target_feature); //~ ERROR the trait bound test(target_feature); //~ ERROR the trait bound

View file

@ -9,8 +9,8 @@ LL | test(target_feature);
note: required by a bound in `test` note: required by a bound in `test`
--> $DIR/fn-exception-target-features.rs:13:17 --> $DIR/fn-exception-target-features.rs:13:17
| |
LL | fn test(f: impl async Fn()) {} LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^^ required by this bound in `test` | ^^^^^^^^^ required by this bound in `test`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -13,7 +13,7 @@ unsafe extern "C" {
pub safe fn abi() -> Pin<Box<dyn Future<Output = ()> + 'static>>; pub safe fn abi() -> Pin<Box<dyn Future<Output = ()> + 'static>>;
} }
fn test(f: impl async Fn()) {} fn test(f: impl AsyncFn()) {}
fn main() { fn main() {
test(unsafety); //~ ERROR the trait bound test(unsafety); //~ ERROR the trait bound

View file

@ -9,8 +9,8 @@ LL | test(unsafety);
note: required by a bound in `test` note: required by a bound in `test`
--> $DIR/fn-exception.rs:16:17 --> $DIR/fn-exception.rs:16:17
| |
LL | fn test(f: impl async Fn()) {} LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^^ required by this bound in `test` | ^^^^^^^^^ 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 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 --> $DIR/fn-exception.rs:20:10
@ -23,8 +23,8 @@ LL | test(abi);
note: required by a bound in `test` note: required by a bound in `test`
--> $DIR/fn-exception.rs:16:17 --> $DIR/fn-exception.rs:16:17
| |
LL | fn test(f: impl async Fn()) {} LL | fn test(f: impl AsyncFn()) {}
| ^^^^^^^^^^ required by this bound in `test` | ^^^^^^^^^ required by this bound in `test`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -6,7 +6,7 @@
extern crate block_on; 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() { fn main() {
block_on::block_on(async { block_on::block_on(async {

View file

@ -12,7 +12,7 @@ extern crate foreign;
struct NoCopy; struct NoCopy;
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await; f().await;
} }

View file

@ -1,7 +1,7 @@
//@ build-pass //@ build-pass
//@ edition: 2021 //@ 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, // 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 // 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 // `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we

View file

@ -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 f().await
} }

View file

@ -13,11 +13,11 @@ use std::future::Future;
use std::pin::pin; use std::pin::pin;
use std::task::*; use std::task::*;
async fn call_mut(f: &mut impl async FnMut()) { async fn call_mut(f: &mut impl AsyncFnMut()) {
f().await; f().await;
} }
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await; f().await;
} }

View file

@ -22,7 +22,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> {
fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()> fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()>
where where
for<'scope> B: async FnOnce(&'scope Scope<'scope, 'env>), for<'scope> B: AsyncFnOnce(&'scope Scope<'scope, 'env>),
{ {
todo!() todo!()
} }

View file

@ -19,7 +19,7 @@ fn main() {
is_static(&c); is_static(&c);
// Check that `<{async fn} as AsyncFnOnce>::CallOnceFuture` owns its captures. // 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)); is_static(&call_once(c));
}); });
} }

View file

@ -9,7 +9,7 @@
extern crate block_on; 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) { pub async fn async_closure(x: &mut i32) {
let c = async move || { let c = async move || {

View file

@ -5,7 +5,7 @@
fn outlives<'a>(_: impl Sized + 'a) {} fn outlives<'a>(_: impl Sized + 'a) {}
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await; f().await;
} }

View file

@ -6,7 +6,7 @@
extern crate block_on; extern crate block_on;
fn wrapper(f: impl Fn(String)) -> impl async Fn(String) { fn wrapper(f: impl Fn(String)) -> impl AsyncFn(String) {
async move |s| f(s) async move |s| f(s)
} }

View file

@ -7,7 +7,7 @@
extern crate block_on; extern crate block_on;
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await; f().await;
} }

View file

@ -5,7 +5,7 @@
//@ revisions: call call_once force_once //@ revisions: call call_once force_once
// call - Call the closure regularly. // call - Call the closure regularly.
// call_once - Call the closure w/ `async FnOnce`, so exercising the by_move shim. // call_once - Call the closure w/ `AsyncFnOnce`, so exercising the by_move shim.
// force_once - Force the closure mode to `FnOnce`, so exercising what was fixed // force_once - Force the closure mode to `FnOnce`, so exercising what was fixed
// in <https://github.com/rust-lang/rust/pull/123350>. // in <https://github.com/rust-lang/rust/pull/123350>.
@ -20,7 +20,7 @@ macro_rules! call {
} }
#[cfg(call_once)] #[cfg(call_once)]
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await f().await
} }
@ -35,7 +35,7 @@ macro_rules! guidance {
} }
#[cfg(force_once)] #[cfg(force_once)]
fn infer_fnonce(c: impl async FnOnce()) -> impl async FnOnce() { c } fn infer_fnonce(c: impl AsyncFnOnce()) -> impl AsyncFnOnce() { c }
#[cfg(force_once)] #[cfg(force_once)]
macro_rules! guidance { macro_rules! guidance {

View file

@ -10,15 +10,15 @@ struct NoCopy;
fn main() { fn main() {
block_on::block_on(async { block_on::block_on(async {
async fn call_once(x: impl async Fn()) { x().await } async fn call_once(x: impl AsyncFn()) { x().await }
// check that `&{async-closure}` implements `async Fn`. // check that `&{async-closure}` implements `AsyncFn`.
call_once(&async || {}).await; call_once(&async || {}).await;
// check that `&{closure}` implements `async Fn`. // check that `&{closure}` implements `AsyncFn`.
call_once(&|| async {}).await; call_once(&|| async {}).await;
// check that `&fndef` implements `async Fn`. // check that `&fndef` implements `AsyncFn`.
async fn foo() {} async fn foo() {}
call_once(&foo).await; call_once(&foo).await;
}); });

View file

@ -3,7 +3,7 @@
#![feature(async_closure)] #![feature(async_closure)]
async fn foo(x: impl async Fn(&str) -> &str) {} async fn foo(x: impl AsyncFn(&str) -> &str) {}
fn main() { fn main() {
foo(async |x| x); foo(async |x| x);

View file

@ -8,7 +8,7 @@
fn outlives<'a>(_: impl Sized + 'a) {} fn outlives<'a>(_: impl Sized + 'a) {}
async fn call_once(f: impl async FnOnce()) { async fn call_once(f: impl AsyncFnOnce()) {
f().await; f().await;
} }

View file

@ -2,7 +2,7 @@
#![feature(async_closure)] #![feature(async_closure)]
fn needs_async_fn(_: impl async Fn()) {} fn needs_async_fn(_: impl AsyncFn()) {}
fn a() { fn a() {
let mut x = 1; let mut x = 1;
@ -15,7 +15,7 @@ fn a() {
fn b() { fn b() {
let x = String::new(); let x = String::new();
needs_async_fn(move || async move { needs_async_fn(move || async move {
//~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` //~^ ERROR expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce`
println!("{x}"); println!("{x}");
}); });
} }

View file

@ -1,29 +1,29 @@
error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce`
--> $DIR/wrong-fn-kind.rs:17:20 --> $DIR/wrong-fn-kind.rs:17:20
| |
LL | needs_async_fn(move || async move { LL | needs_async_fn(move || async move {
| -------------- -^^^^^^ | -------------- -^^^^^^
| | | | | |
| _____|______________this closure implements `async FnOnce`, not `async Fn` | _____|______________this closure implements `AsyncFnOnce`, not `AsyncFn`
| | | | | |
| | required by a bound introduced by this call | | required by a bound introduced by this call
LL | | LL | |
LL | | println!("{x}"); LL | | println!("{x}");
| | - closure is `async FnOnce` because it moves the variable `x` out of its environment | | - closure is `AsyncFnOnce` because it moves the variable `x` out of its environment
LL | | }); LL | | });
| |_____- the requirement to implement `async Fn` derives from here | |_____- the requirement to implement `AsyncFn` derives from here
| |
note: required by a bound in `needs_async_fn` note: required by a bound in `needs_async_fn`
--> $DIR/wrong-fn-kind.rs:5:27 --> $DIR/wrong-fn-kind.rs:5:27
| |
LL | fn needs_async_fn(_: impl async Fn()) {} LL | fn needs_async_fn(_: impl AsyncFn()) {}
| ^^^^^^^^^^ required by this bound in `needs_async_fn` | ^^^^^^^^^ required by this bound in `needs_async_fn`
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
--> $DIR/wrong-fn-kind.rs:9:20 --> $DIR/wrong-fn-kind.rs:9:20
| |
LL | fn needs_async_fn(_: impl async Fn()) {} LL | fn needs_async_fn(_: impl AsyncFn()) {}
| --------------- change this to accept `FnMut` instead of `Fn` | -------------- change this to accept `FnMut` instead of `Fn`
... ...
LL | needs_async_fn(async || { LL | needs_async_fn(async || {
| -------------- ^^^^^^^^ | -------------- ^^^^^^^^

View file

@ -2,7 +2,7 @@
#![feature(async_closure)] #![feature(async_closure)]
fn foo(x: &dyn async Fn()) {} fn foo(x: &dyn AsyncFn()) {}
//~^ ERROR the trait `AsyncFnMut` cannot be made into an object //~^ ERROR the trait `AsyncFnMut` cannot be made into an object
fn main() {} fn main() {}

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `AsyncFnMut` cannot be made into an object error[E0038]: the trait `AsyncFnMut` cannot be made into an object
--> $DIR/dyn-pos.rs:5:16 --> $DIR/dyn-pos.rs:5:16
| |
LL | fn foo(x: &dyn async Fn()) {} LL | fn foo(x: &dyn AsyncFn()) {}
| ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object | ^^^^^^^^^ `AsyncFnMut` cannot be made into an object
| |
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL

View file

@ -1,8 +1,8 @@
fn foo(x: impl async Fn()) -> impl async Fn() { x } fn foo(x: impl async Fn()) -> impl async Fn() { x }
//~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later //~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later
//~| ERROR `async` trait bounds are only allowed in Rust 2018 or later //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later
//~| ERROR async closures are unstable //~| ERROR `async` trait bounds are unstable
//~| ERROR async closures are unstable //~| ERROR `async` trait bounds are unstable
//~| ERROR use of unstable library feature `async_closure` //~| ERROR use of unstable library feature `async_closure`
//~| ERROR use of unstable library feature `async_closure` //~| ERROR use of unstable library feature `async_closure`

View file

@ -16,27 +16,27 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
= help: pass `--edition 2024` to `rustc` = help: pass `--edition 2024` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide = note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0658]: async closures are unstable error[E0658]: `async` trait bounds are unstable
--> $DIR/edition-2015.rs:1:16 --> $DIR/edition-2015.rs:1:16
| |
LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
| ^^^^^ | ^^^^^
| |
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {` = help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: async closures are unstable error[E0658]: `async` trait bounds are unstable
--> $DIR/edition-2015.rs:1:36 --> $DIR/edition-2015.rs:1:36
| |
LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
| ^^^^^ | ^^^^^
| |
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {` = help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: use of unstable library feature `async_closure` error[E0658]: use of unstable library feature `async_closure`
--> $DIR/edition-2015.rs:1:42 --> $DIR/edition-2015.rs:1:42

View file

@ -15,7 +15,7 @@ async fn f(arg: &i32) {}
async fn func<F>(f: F) async fn func<F>(f: F)
where where
F: for<'a> async Fn(&'a i32), F: for<'a> AsyncFn(&'a i32),
{ {
let x: i32 = 0; let x: i32 = 0;
f(&x).await; f(&x).await;

View file

@ -3,13 +3,13 @@
#![feature(async_closure, type_alias_impl_trait)] #![feature(async_closure, type_alias_impl_trait)]
type Tait = impl async Fn(); type Tait = impl AsyncFn();
fn tait() -> Tait { fn tait() -> Tait {
|| async {} || async {}
} }
fn foo(x: impl async Fn()) -> impl async Fn() { x } fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x }
fn param<T: async Fn()>() {} fn param<T: AsyncFn()>() {}
fn main() {} fn main() {}

View file

@ -13,9 +13,9 @@ macro_rules! demo {
} }
demo! { impl async Trait } demo! { impl async Trait }
//~^ ERROR async closures are unstable //~^ ERROR `async` trait bounds are unstable
demo! { dyn async Trait } demo! { dyn async Trait }
//~^ ERROR async closures are unstable //~^ ERROR `async` trait bounds are unstable
fn main() {} fn main() {}

View file

@ -20,27 +20,27 @@ LL | demo! { dyn async Trait }
| |
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: async closures are unstable error[E0658]: `async` trait bounds are unstable
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14 --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14
| |
LL | demo! { impl async Trait } LL | demo! { impl async Trait }
| ^^^^^ | ^^^^^
| |
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {` = help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: async closures are unstable error[E0658]: `async` trait bounds are unstable
--> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13 --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13
| |
LL | demo! { dyn async Trait } LL | demo! { dyn async Trait }
| ^^^^^ | ^^^^^
| |
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {` = help: use the desugared name of the async trait, such as `AsyncFn`
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View file

@ -1,6 +1,6 @@
//@ edition:2018 //@ edition:2018
#![feature(async_closure)] #![feature(async_trait_bounds)]
struct S; struct S;

View file

@ -6,7 +6,9 @@
#![feature(async_closure, unboxed_closures, async_fn_traits)] #![feature(async_closure, unboxed_closures, async_fn_traits)]
fn project<F: async Fn<()>>(_: F) -> Option<F::Output> { None } use std::ops::AsyncFn;
fn project<F: AsyncFn<()>>(_: F) -> Option<F::Output> { None }
fn main() { fn main() {
let x: Option<i32> = project(|| async { 1i32 }); let x: Option<i32> = project(|| async { 1i32 });

View file

@ -1,7 +1,7 @@
//@ edition: 2021 //@ edition: 2021
//@ check-pass //@ check-pass
#![feature(async_closure)] #![feature(async_closure, async_trait_bounds)]
async fn foo() {} async fn foo() {}

View file

@ -6,7 +6,7 @@ macro_rules! x {
x! { x! {
async fn foo() -> impl async Fn() { } async fn foo() -> impl async Fn() { }
//~^ ERROR async closures are unstable //~^ ERROR `async` trait bounds are unstable
} }
fn main() {} fn main() {}

View file

@ -1,13 +1,13 @@
error[E0658]: async closures are unstable error[E0658]: `async` trait bounds are unstable
--> $DIR/trait-bounds-in-macro.rs:8:28 --> $DIR/trait-bounds-in-macro.rs:8:28
| |
LL | async fn foo() -> impl async Fn() { } LL | async fn foo() -> impl async Fn() { }
| ^^^^^ | ^^^^^
| |
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {` = help: use the desugared name of the async trait, such as `AsyncFn`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,6 +1,6 @@
//@ edition:2018 //@ edition:2018
#![feature(async_closure)] #![feature(async_trait_bounds)]
trait Foo {} trait Foo {}

View file

@ -0,0 +1,7 @@
//@ edition: 2021
fn test(_: impl async Fn()) {}
//~^ ERROR `async` trait bounds are unstable
//~| ERROR use of unstable library feature `async_closure`
fn main() {}

View file

@ -0,0 +1,24 @@
error[E0658]: `async` trait bounds are unstable
--> $DIR/feature-gate-async-trait-bounds.rs:3:17
|
LL | fn test(_: impl async Fn()) {}
| ^^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: use of unstable library feature `async_closure`
--> $DIR/feature-gate-async-trait-bounds.rs:3:23
|
LL | fn test(_: impl async Fn()) {}
| ^^^^
|
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -7,7 +7,7 @@ fn polarity() -> impl Sized + ?use<> {}
fn asyncness() -> impl Sized + async use<> {} fn asyncness() -> impl Sized + async use<> {}
//~^ ERROR expected identifier, found keyword `use` //~^ ERROR expected identifier, found keyword `use`
//~| ERROR cannot find trait `r#use` in this scope //~| ERROR cannot find trait `r#use` in this scope
//~| ERROR async closures are unstable //~| ERROR `async` trait bounds are unstable
fn constness() -> impl Sized + const use<> {} fn constness() -> impl Sized + const use<> {}
//~^ ERROR expected identifier, found keyword `use` //~^ ERROR expected identifier, found keyword `use`

View file

@ -46,16 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope
LL | fn binder() -> impl Sized + for<'a> use<> {} LL | fn binder() -> impl Sized + for<'a> use<> {}
| ^^^ not found in this scope | ^^^ not found in this scope
error[E0658]: async closures are unstable error[E0658]: `async` trait bounds are unstable
--> $DIR/bound-modifiers.rs:7:32 --> $DIR/bound-modifiers.rs:7:32
| |
LL | fn asyncness() -> impl Sized + async use<> {} LL | fn asyncness() -> impl Sized + async use<> {}
| ^^^^^ | ^^^^^
| |
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {` = help: use the desugared name of the async trait, such as `AsyncFn`
error[E0658]: const trait impls are experimental error[E0658]: const trait impls are experimental
--> $DIR/bound-modifiers.rs:12:32 --> $DIR/bound-modifiers.rs:12:32

View file

@ -12,6 +12,6 @@ macro_rules! impl_primitive {
impl_primitive!(impl async); impl_primitive!(impl async);
//~^ ERROR expected identifier, found `<eof>` //~^ ERROR expected identifier, found `<eof>`
//~| ERROR async closures are unstable //~| ERROR `async` trait bounds are unstable
fn main() {} fn main() {}

View file

@ -7,16 +7,16 @@ LL | ($ty:ty) => {
LL | impl_primitive!(impl async); LL | impl_primitive!(impl async);
| ^^^^^ expected identifier | ^^^^^ expected identifier
error[E0658]: async closures are unstable error[E0658]: `async` trait bounds are unstable
--> $DIR/bad-recover-kw-after-impl.rs:13:22 --> $DIR/bad-recover-kw-after-impl.rs:13:22
| |
LL | impl_primitive!(impl async); LL | impl_primitive!(impl async);
| ^^^^^ | ^^^^^
| |
= note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
= help: add `#![feature(async_closure)]` to the crate attributes to enable = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= help: to use an async block, remove the `||`: `async {` = help: use the desugared name of the async trait, such as `AsyncFn`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors