Skip to content

Conversation

@heathdutton
Copy link
Contributor

@heathdutton heathdutton commented Jan 1, 2026

When an async closure captures a variable by move but is constrained to AsyncFn or AsyncFnMut, the error message now explains that the closure kind is the issue and points to the trait bound, similar to the existing diagnostic for Fn/FnMut closures.

Before:

error[E0507]: cannot move out of `foos` which is behind a shared reference
  --> src/lib.rs:12:20
   |
11 | async fn foo(foos: &mut [&mut Foo]) -> Result<(), ()> {
   |              ---- move occurs because `foos` has type...
12 |     in_transaction(async || -> Result<(), ()> {
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ `foos` is moved here
13 |         for foo in foos {
   |                    ---- variable moved due to use in coroutine

After:

error[E0507]: cannot move out of `y`, a captured variable in an `AsyncFn` closure
  --> src/lib.rs:9:10
   |
LL |     let y = vec![format!("World")];
   |         - captured outer variable
LL |     call(async || {
   |          ^^^^^^^^ captured by this `AsyncFn` closure
...
help: `AsyncFn` and `AsyncFnMut` closures require captured values to be able
      to be consumed multiple times, but `AsyncFnOnce` closures may consume
      them only once
  --> src/lib.rs:5:27
   |
LL | fn call<F>(_: F) where F: AsyncFn() {}
   |                           ^^^^^^^^^

Fixes #150174

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 1, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 1, 2026

r? @mati865

rustbot has assigned @mati865.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot

This comment has been minimized.

@heathdutton heathdutton force-pushed the issue-150174-asyncfn-diagnostic-v2 branch from d65f71a to 9ef09ef Compare January 2, 2026 03:47
@mati865
Copy link
Member

mati865 commented Jan 12, 2026

@rustbot reroll

Hopefully another reviewer will have better knowledge about #150572 (comment)

@rustbot rustbot assigned lcnr and unassigned mati865 Jan 12, 2026
@heathdutton

This comment was marked as outdated.

@heathdutton heathdutton marked this pull request as draft January 19, 2026 15:49
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 19, 2026
@heathdutton heathdutton force-pushed the issue-150174-asyncfn-diagnostic-v2 branch from 9ef09ef to d6a8c72 Compare January 21, 2026 18:27
@heathdutton

This comment was marked as outdated.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 21, 2026
@heathdutton heathdutton marked this pull request as ready for review January 21, 2026 18:27
@rust-log-analyzer

This comment has been minimized.

@heathdutton heathdutton force-pushed the issue-150174-asyncfn-diagnostic-v2 branch 2 times, most recently from 48c7d9e to 0f81d39 Compare January 21, 2026 18:51
@rustbot
Copy link
Collaborator

rustbot commented Jan 21, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Copy link
Contributor

@lcnr lcnr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heathdutton heathdutton force-pushed the issue-150174-asyncfn-diagnostic-v2 branch from 0f81d39 to 5088318 Compare January 28, 2026 17:01
@lcnr
Copy link
Contributor

lcnr commented Jan 28, 2026

after nit

@bors delegate+

@rust-bors
Copy link
Contributor

rust-bors bot commented Jan 28, 2026

✌️ @heathdutton, you can now approve this pull request!

If @lcnr told you to "r=me" after making some further change, then please make that change and post @bors r=lcnr.

When an async closure captures a variable by move but is constrained to
`AsyncFn` or `AsyncFnMut`, the error message now explains that the
closure kind is the issue and points to the trait bound, similar to the
existing diagnostic for `Fn`/`FnMut` closures.
@heathdutton heathdutton force-pushed the issue-150174-asyncfn-diagnostic-v2 branch from 5088318 to f5f2ca0 Compare January 28, 2026 18:19
@heathdutton
Copy link
Contributor Author

@bors r=lcnr

@rust-bors
Copy link
Contributor

rust-bors bot commented Jan 28, 2026

📌 Commit f5f2ca0 has been approved by lcnr

It is now in the queue for this repository.

@rust-bors rust-bors bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 28, 2026
Zalathar added a commit to Zalathar/rust that referenced this pull request Jan 29, 2026
…iagnostic-v2, r=lcnr

Improve move error diagnostic for `AsyncFn` closures

When an async closure captures a variable by move but is constrained to `AsyncFn` or `AsyncFnMut`, the error message now explains that the closure kind is the issue and points to the trait bound, similar to the existing diagnostic for `Fn`/`FnMut` closures.

**Before:**
```
error[E0507]: cannot move out of `foos` which is behind a shared reference
  --> src/lib.rs:12:20
   |
11 | async fn foo(foos: &mut [&mut Foo]) -> Result<(), ()> {
   |              ---- move occurs because `foos` has type...
12 |     in_transaction(async || -> Result<(), ()> {
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ `foos` is moved here
13 |         for foo in foos {
   |                    ---- variable moved due to use in coroutine
```

**After:**
```
error[E0507]: cannot move out of `y`, a captured variable in an `AsyncFn` closure
  --> src/lib.rs:9:10
   |
LL |     let y = vec![format!("World")];
   |         - captured outer variable
LL |     call(async || {
   |          ^^^^^^^^ captured by this `AsyncFn` closure
...
help: `AsyncFn` and `AsyncFnMut` closures require captured values to be able
      to be consumed multiple times, but `AsyncFnOnce` closures may consume
      them only once
  --> src/lib.rs:5:27
   |
LL | fn call<F>(_: F) where F: AsyncFn() {}
   |                           ^^^^^^^^^
```

Fixes rust-lang#150174
rust-bors bot pushed a commit that referenced this pull request Jan 29, 2026
Rollup of 8 pull requests

Successful merges:

 - #150474 (Tidy: detect ui tests subdirectory changes so `tests/ui/README.md` stays in sync)
 - #150572 (Improve move error diagnostic for `AsyncFn` closures)
 - #151596 (Fix -Zmir-enable-passes to detect unregistered enum names in declare_passes macro)
 - #151802 (Make `QueryDispatcher::Qcx` an associated type)
 - #151559 ([rustdoc] Add a marker to tell users that there are hidden (deprecated) items in the search results)
 - #151665 (Fix contrast ratio for `Since` element in rustodoc dark theme)
 - #151798 (Update `askama` to `0.15.3`)
 - #151800 (Subscribe myself to translation diagnostics)
rust-bors bot pushed a commit that referenced this pull request Jan 29, 2026
Rollup of 12 pull requests

Successful merges:

 - #150474 (Tidy: detect ui tests subdirectory changes so `tests/ui/README.md` stays in sync)
 - #150572 (Improve move error diagnostic for `AsyncFn` closures)
 - #151596 (Fix -Zmir-enable-passes to detect unregistered enum names in declare_passes macro)
 - #151802 (Make `QueryDispatcher::Qcx` an associated type)
 - #149110 (Implement `cast_slice` for raw pointer types)
 - #151559 ([rustdoc] Add a marker to tell users that there are hidden (deprecated) items in the search results)
 - #151665 (Fix contrast ratio for `Since` element in rustdoc dark theme)
 - #151785 (Stabilize feature(push_mut))
 - #151798 (Update `askama` to `0.15.3`)
 - #151800 (Subscribe myself to translation diagnostics)
 - #151804 (Document, sort, and tweak spellcheck entries in `typos.toml`)
 - #151805 (Fix grammar in `env::current_exe()#Security`)
@rust-bors rust-bors bot merged commit 9f551d3 into rust-lang:main Jan 29, 2026
11 checks passed
@rustbot rustbot added this to the 1.95.0 milestone Jan 29, 2026
rust-timer added a commit that referenced this pull request Jan 29, 2026
Rollup merge of #150572 - heathdutton:issue-150174-asyncfn-diagnostic-v2, r=lcnr

Improve move error diagnostic for `AsyncFn` closures

When an async closure captures a variable by move but is constrained to `AsyncFn` or `AsyncFnMut`, the error message now explains that the closure kind is the issue and points to the trait bound, similar to the existing diagnostic for `Fn`/`FnMut` closures.

**Before:**
```
error[E0507]: cannot move out of `foos` which is behind a shared reference
  --> src/lib.rs:12:20
   |
11 | async fn foo(foos: &mut [&mut Foo]) -> Result<(), ()> {
   |              ---- move occurs because `foos` has type...
12 |     in_transaction(async || -> Result<(), ()> {
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ `foos` is moved here
13 |         for foo in foos {
   |                    ---- variable moved due to use in coroutine
```

**After:**
```
error[E0507]: cannot move out of `y`, a captured variable in an `AsyncFn` closure
  --> src/lib.rs:9:10
   |
LL |     let y = vec![format!("World")];
   |         - captured outer variable
LL |     call(async || {
   |          ^^^^^^^^ captured by this `AsyncFn` closure
...
help: `AsyncFn` and `AsyncFnMut` closures require captured values to be able
      to be consumed multiple times, but `AsyncFnOnce` closures may consume
      them only once
  --> src/lib.rs:5:27
   |
LL | fn call<F>(_: F) where F: AsyncFn() {}
   |                           ^^^^^^^^^
```

Fixes #150174
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E0507: AsyncFn vs AsyncFnOnce not given as cause of error, unlike Fn vs FnOnce

5 participants