Skip to content

Lifetime is unnecessarily captured in nested functions returning impl trait via async #63032

@sfackler

Description

@sfackler

When trying to create some futures that do a bit of work up-front to avoid borrowing some inputs, I ran into this strange issue where it seems like an input lifetime is being unnecessarily captured by the returned impl trait even though the value isn't:

#![feature(async_await)]
use std::future::Future;

fn query<'a, I>(params: I) -> impl Future<Output = Vec<i32>> + 'static
where
    I: IntoIterator<Item = &'a i32>,
{
    let start = start(params);
    
    async {
        start.await
    }
}

fn start<'a, I>(params: I) -> impl Future<Output = Vec<i32>> + 'static
where
    I: IntoIterator<Item = &'a i32>,
{
    let buf = encode(params);
    
    async {
        buf
    }
}

fn encode<'a, I>(params: I) -> Vec<i32>
where
    I: IntoIterator<Item = &'a i32>,
{
    params.into_iter().cloned().collect()
}
error[E0310]: the parameter type `I` may not live long enough
 --> src/lib.rs:4:31
  |
4 | fn query<'a, I>(params: I) -> impl Future<Output = Vec<i32>> + 'static
  |              -                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |              |
  |              help: consider adding an explicit lifetime bound `I: 'static`...
  |
note: ...so that the type `impl std::future::Future` will meet its required lifetime bounds
 --> src/lib.rs:4:31
  |
4 | fn query<'a, I>(params: I) -> impl Future<Output = Vec<i32>> + 'static
  |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0310`.

It also seems really weird that this only happens with 2 layers of "nesting" - start compiles just fine, but query doesn't even though it's pretty much just a pass-through.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.AsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions