rust-lang / rust-lang/rust

Incorrect error about lifetimes with Send bound on AsyncFnMut::CallRefFuture

Open
#153,558 5 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-GATs A-higher-ranked C-bug D-newcomer-roadblock D-papercut T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

This program builds fine (playground):

/// Provides zero to an async function.
fn provide_zero<'a, F>(f: &'a mut F) -> impl Future<Output = ()> + 'a
where
    F: AsyncFnMut(i32),
{
    async { f(0).await }
}

/// Builds a vector containing zero in a really silly way.
async fn foo() -> Vec<i32> {
    let mut v = Vec::new();
    provide_zero(&mut async |n| v.push(n)).await;
    v
}

However, if you change provide_zero to require that the closure it accepts returns a future that can be polled in a multi-threaded environment, it stops compiling, with an incorrect error about v not living long enough in foo (playground):

fn provide_zero<'a, F>(f: &'a mut F) -> impl Future<Output = ()> + 'a
where
    F: AsyncFnMut(i32),
    for<'b> F::CallRefFuture<'b>: Send,
{
    async { f(0).await }
}
   Compiling playground v0.0.1 (/playground)
error[E0597]: `v` does not live long enough
  --> src/lib.rs:18:23
   |
18 |     provide_zero(&mut async |n| v.push(n)).await;
   |     ------------------^^^^^^^^^^^^^^^^^^^-
   |     |                 |
   |     |                 borrowed value does not live long enough
   |     argument requires that `v` is borrowed for `'static`
19 |     v
20 | }
   | - `v` dropped here while still borrowed
   |
note: due to a current limitation of the type system, this implies a `'static` lifetime
  --> src/lib.rs:10:5
   |
10 |     for<'b> F::CallRefFuture<'b>: Send,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From the note it seems clear this is a consequence of some known issue. But what known issue? What are the prospects for resolving it? (Googling the note only turns up #150081, which doesn't really tell me the answer.)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing both nightly examples in the linked Rust Playground, comparing the versions of provide_zero and the AsyncFnMut::CallRefFuture Send bound. Trace the compiler limitation described in the diagnostic and determine which known issue it relates to; done means documenting the cause and realistic prospects for resolution.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.