-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
async move closure owning Fn and calling it #128516
Labels
Comments
I'll look into it. I agree that something particularly weird is going on here -- each future returned by calling the |
rust-timer
added a commit
to rust-lang-ci/rust
that referenced
this issue
Aug 8, 2024
Rollup merge of rust-lang#128520 - compiler-errors:more-precisely-force-move, r=BoxyUwU Skip over args when determining if async-closure's inner coroutine consumes its upvars rust-lang#125306 implements a strategy for when we have an `async move ||` async-closure that is inferred to be `async FnOnce`, it will force the inner coroutine to also be `move`, since we cannot borrow any upvars from the parent async-closure (since `FnOnce` is not lending): https://github.com/rust-lang/rust/blob/8e86c9567154dc5a9ada15ab196d23eae2bd7d89/compiler/rustc_hir_typeck/src/upvar.rs#L211-L229 However, when this strategy was implemented, it reused the `ExprUseVisitor` data from visiting the whole coroutine, which includes additional statements due to `async`-specific argument desugaring: https://github.com/rust-lang/rust/blob/8e86c9567154dc5a9ada15ab196d23eae2bd7d89/compiler/rustc_ast_lowering/src/item.rs#L1197-L1228 Well, it turns out that we don't care about these argument desugaring parameters, because arguments to the async-closure are not the *async-closure*'s captures -- they exist for only one invocation of the closure, and they're always consumed by construction (see the argument desugaring above), so they will force the coroutine's inferred kind to `FnOnce`. (Unless they're `Copy`, because we never consider `Copy` types to be consumed): https://github.com/rust-lang/rust/blob/8e86c9567154dc5a9ada15ab196d23eae2bd7d89/compiler/rustc_hir_typeck/src/expr_use_visitor.rs#L60-L66 However, since we *were* visiting these arg exprs, this resulted in us too-aggressively applying `move` to the inner coroutine, resulting in regressions. For example, this PR fixes rust-lang#128516. Fascinatingly, the note above about how we never consume `Copy` types is why this only regressed when the argument types weren't all `Copy`. I tried to leave some comments inline to make this more clear :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tried this code (https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=1062a9d9bd18705abc0f2109c7df7ef3):
I expected to see this happen: this compiles successfully. In my understanding of async closures, the closure should own
f
but its returned future should borrow it from the closure, leading to no error. Furthermore, if all of returned closure's arguments areCopy
, this compiles successfully - I don't think the arguments' types should change anything.Instead, this happened: it errors with:
@rustbot label +F-async_closure
The text was updated successfully, but these errors were encountered: