Skip to content

async closure does not implement FnMut because it captures state from its environment for async closures, while closure returning async block works fine #125247

Closed
@peku33

Description

@peku33

I've returned to one of my projects after a few months of pause. Before I was using rust nigthly ~1.7x (around November 2023). It also worked through whole 2022 and 2021 IIRC. I've moved to new computer and installed rust nightly 1.80 (latest).

After upgrading I noticed that my whole codebase is full of errors around async move |foo| capturing something from environment.
error: async closure does not implement `FnMut` because it captures state from its environment. However if I change async |_| { ... } to |_| async { ... } it builds and works like previosly.

Minimal example below.

#![feature(async_closure)]

use futures::StreamExt;

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let test = Test {};

    test.async_with_async_closure().await;
}

struct Test {}
impl Test {
    // This is how it used to work, but now it does not compile
    async fn async_with_async_closure(&self) {
        futures::stream::repeat(())
            .take(5)
            .for_each(async |_item| { // the difference is here
                self.sync_method();
            }).await;
    }
    
    // This is the workaround
    async fn async_with_async_block(&self) {
        futures::stream::repeat(())
            .take(5)
            .for_each(|_item| async { // the difference is here
                self.sync_method();
            }).await;
    }

    fn sync_method(&self) {
        println!("i am being called");
    }
}

The error for first method is:

   Compiling playground v0.0.1 (/playground)
error: async closure does not implement `FnMut` because it captures state from its environment
    --> src/main.rs:17:23
     |
17   |             .for_each(async |_item| {
     |              -------- ^^^^^^^^^^^^^
     |              |
     |              required by a bound introduced by this call
     |
note: required by a bound in `futures::StreamExt::for_each`
    --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/futures-util-0.3.30/src/stream/stream/mod.rs:1093:12
     |
1091 |     fn for_each<Fut, F>(self, f: F) -> ForEach<Self, Fut, F>
     |        -------- required by a bound in this associated function
1092 |     where
1093 |         F: FnMut(Self::Item) -> Fut,
     |            ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StreamExt::for_each`

error: async closure does not implement `FnMut` because it captures state from its environment
  --> src/main.rs:17:23
   |
17 |             .for_each(async |_item| {
   |                       ^^^^^^^^^^^^^
   |
   = note: required for `ForEach<Take<Repeat<()>>, {async closure body@src/main.rs:17:37: 19:14}, {async [email protected]:17:23}>` to implement `futures::Future`
   = note: required for `ForEach<Take<Repeat<()>>, {async closure body@src/main.rs:17:37: 19:14}, {async [email protected]:17:23}>` to implement `std::future::IntoFuture`
   = note: the full name for the type has been written to '/playground/target/debug/deps/playground-71f1e6caf9dc6471.long-type-11561845803583376377.txt'
   = note: consider using `--verbose` to print the full type name to the console
   = note: the full name for the type has been written to '/playground/target/debug/deps/playground-71f1e6caf9dc6471.long-type-11561845803583376377.txt'
   = note: consider using `--verbose` to print the full type name to the console

error: could not compile `playground` (bin "playground") due to 2 previous errors

i booted my very old PC to check, this is definately not the last version this worked fine:
rustc 1.70.0-nightly (ab654863c 2023-03-15)
I definately does not work with:
rustc 1.80.0-nightly (8387315ab 2024-05-14)

Metadata

Metadata

Labels

A-async-closures`async || {}`C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions