Skip to content

Compiler error "implementation of Send is not general enough" when using static lifetime reference with async closure #138494

Open
@zhuerzhuer

Description

@zhuerzhuer

I tried this code:

#[cfg(test)]
mod tests {
    use std::sync::OnceLock;

    struct MySystem {
        _state: u32,
    }

    impl MySystem {
        async fn print(&self, buff: &[u8]) {
            println!("MySystem: {:?}", buff)
        }
    }

    static SYSTEM: OnceLock<MySystem> = OnceLock::new();

    #[tokio::test]
    async fn test_async_closure() {
        SYSTEM.get_or_init(|| MySystem { _state: 1 });

        // The commented code produces the error:
        // tokio::spawn(async {
        //     let sys: &'static OnceLock<MySystem> = &SYSTEM;
        //     loop {
        //         recv_message(async move |buff| {
        //             hand_message(sys, buff).await;
        //         })
        //         .await;
        //     }
        // });

        // This uncommented version is ok:
        tokio::spawn(async {
            loop {
                recv_message(async move |buff| {
                    hand_message(&SYSTEM, buff).await;
                })
                .await;
            }
        });
    }

    async fn recv_message<T>(mut handle: T)
    where
        T: AsyncFnMut(&[u8]),
    {
        let buff = [0u8];
        handle(&buff).await;
    }

    async fn hand_message(system: &'static OnceLock<MySystem>, buff: &[u8]) {
        system.get().unwrap().print(buff).await;
    }
}

I expected to see this happen:
I expect the commented code to compile without errors
Instead, this happened:
The commented code produces a compile error: implementation of Send is not general enough.

Meta

rustc --version --verbose:

rustc 1.85.0 (4d91de4e4 2025-02-17)
binary: rustc
commit-hash: 4d91de4e48198da2e33413efdcd9cd2cc0c46688
commit-date: 2025-02-17
host: x86_64-pc-windows-msvc
release: 1.85.0
LLVM version: 19.1.7

Tokio version: 1.42.0
Backtrace

implementation of `Send` is not general enough
`Send` would have to be implemented for the type `&'0 OnceLock<MySystem>`, for any lifetime `'0`...
...but `Send` is actually implemented for the type `&'1 OnceLock<MySystem>`, for some specific lifetime `'1`

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-closures`async || {}`A-lifetimesArea: Lifetimes / regionsA-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types 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