You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Rust incorrectly detects move'd async closure as FnOnce instead of Fn on nightly-2024-02-07 #120957
error[E0277]: expected a `Fn()` closure, found `{async closure@src\main.rs:8:19: 8:32}`
--> src\main.rs:11:10
|
11 | test(example);
| ---- ^^^^^^^ expected an `Fn()` closure, found `{async closure@src\main.rs:8:19: 8:32}`
| |
| required by a bound introduced by this call
|
= help: the trait `Fn<()>` is not implemented for `{async closure@src\main.rs:8:19: 8:32}`
= note: wrap the `{async closure@src\main.rs:8:19: 8:32}` in a closure with no arguments: `|| { /* code */ }`
= note: `{async closure@src\main.rs:8:19: 8:32}` implements `FnOnce`, but it must implement `Fn`, which is more general
This bug was introduced between nightly-2024-02-06 (where the code builds correctly) and nightly-2024-02-27 (where the error happens), and is still present on nightly-2024-02-11 (the latest when this was released). This bug is likely related to #120886, which was fixed by #120712.
@BigBadE: This is somewhat expected behavior after the async closure refactor. Try writing your fn test like:
fn test(given: impl async Fn() -> T) {}
If this isn't working out in practice, pls share more information about what you're trying to use async closures for.
Okay, so async closures now are of the AsyncFn trait instead of the Fn trait, which breaks any code that previously expected them to be of the Fn trait. https://rust-lang.github.io/async-fundamentals-initiative/roadmap/async_closures.html explains the issue, but I can't help but wonder how async closures used to work when they did implement the Fn trait.
Either way, the problem is solved as long as this isn't considered a regression.
I can't help but wonder how async closures used to work when they did implement the Fn trait.
Async closures used to just be closures that return async blocks. In other words, another fix for your issue is to just write move || async move {} instead of async move || {}, since before I reworked them, that's literally just what they desugared to.
I do encourage you to try out "better" async closures; the where clause bounds for your test example function are pretty restrictive in practice, as you can't borrow any state from the closure, which should "just work" with the new async closures.
I'd love to hear more about how your project(s) are using async closures and whether you're able to express more with the new async Fn() bounds, though -- feel free to shoot me a message on Zulip if you've got more questions or comments.
Activity
Noratrieb commentedon Feb 12, 2024
@compiler-errors more async closure fun :3
compiler-errors commentedon Feb 12, 2024
@BigBadE: This is somewhat expected behavior after the async closure refactor. Try writing your
fn testlike:If this isn't working out in practice, pls share more information about what you're trying to use async closures for.
BigBadE commentedon Feb 12, 2024
Okay, so async closures now are of the AsyncFn trait instead of the Fn trait, which breaks any code that previously expected them to be of the Fn trait. https://rust-lang.github.io/async-fundamentals-initiative/roadmap/async_closures.html explains the issue, but I can't help but wonder how async closures used to work when they did implement the Fn trait.
Either way, the problem is solved as long as this isn't considered a regression.
compiler-errors commentedon Feb 12, 2024
@BigBadE:
Async closures used to just be closures that return async blocks. In other words, another fix for your issue is to just write
move || async move {}instead ofasync move || {}, since before I reworked them, that's literally just what they desugared to.I do encourage you to try out "better" async closures; the where clause bounds for your
testexample function are pretty restrictive in practice, as you can't borrow any state from the closure, which should "just work" with the new async closures.I'd love to hear more about how your project(s) are using async closures and whether you're able to express more with the new
async Fn()bounds, though -- feel free to shoot me a message on Zulip if you've got more questions or comments.