From ff07f55db500dafb2d6570b5de7928bcc10a955f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Feb 2024 01:36:08 +0000 Subject: [PATCH] Actually use the right closure kind when checking async Fn goals --- .../src/traits/select/confirmation.rs | 5 ++-- .../async-closures/wrong-fn-kind.rs | 8 ++++-- .../async-closures/wrong-fn-kind.stderr | 27 ++++++++++++++++--- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f76be87694886..d316149731e14 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -934,7 +934,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (trait_ref, Ty::from_closure_kind(tcx, ty::ClosureKind::Fn)) } ty::Closure(_, args) => { - let sig = args.as_closure().sig(); + let args = args.as_closure(); + let sig = args.sig(); let trait_ref = sig.map_bound(|sig| { ty::TraitRef::new( self.tcx(), @@ -950,7 +951,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]) }), )); - (trait_ref, Ty::from_closure_kind(tcx, ty::ClosureKind::Fn)) + (trait_ref, args.kind_ty()) } _ => bug!("expected callable type for AsyncFn candidate"), }; diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs index 7c3c7337e2ef0..8502bb6e2d45d 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -1,7 +1,5 @@ //@ edition:2021 -// FIXME(async_closures): This needs a better error message! - #![feature(async_closure)] fn main() { @@ -12,4 +10,10 @@ fn main() { //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut` x += 1; }); + + let x = String::new(); + needs_async_fn(move || async move { + //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` + println!("{x}"); + }); } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index 34a6b3a485a60..d0f1948e48f83 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -1,5 +1,5 @@ error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut` - --> $DIR/wrong-fn-kind.rs:11:20 + --> $DIR/wrong-fn-kind.rs:9:20 | LL | needs_async_fn(async || { | -------------- -^^^^^^^ @@ -14,11 +14,32 @@ LL | | }); | |_____- the requirement to implement `async Fn` derives from here | note: required by a bound in `needs_async_fn` - --> $DIR/wrong-fn-kind.rs:8:31 + --> $DIR/wrong-fn-kind.rs:6:31 | LL | fn needs_async_fn(_: impl async Fn()) {} | ^^^^^^^^^^ required by this bound in `needs_async_fn` -error: aborting due to 1 previous error +error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` + --> $DIR/wrong-fn-kind.rs:15:20 + | +LL | needs_async_fn(move || async move { + | -------------- -^^^^^^ + | | | + | _____|______________this closure implements `async FnOnce`, not `async Fn` + | | | + | | required by a bound introduced by this call +LL | | +LL | | println!("{x}"); + | | - closure is `async FnOnce` because it moves the variable `x` out of its environment +LL | | }); + | |_____- the requirement to implement `async Fn` derives from here + | +note: required by a bound in `needs_async_fn` + --> $DIR/wrong-fn-kind.rs:6:31 + | +LL | fn needs_async_fn(_: impl async Fn()) {} + | ^^^^^^^^^^ required by this bound in `needs_async_fn` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0525`.