Skip to content

Unexpected "the parameter type X may not live long enough" error in asynchronous functions #95719

Open
@wvwwvwwv

Description

When a Future is wrapped in an async block or an async function, some of its traits are lost, e.g., Send, thus causing various issues.

I tried this code:

#![feature(impl_trait_in_assoc_type)]

use std::future::Future;

pub trait Get: Send + Sync {
    type Ret<'a>: Future<Output = usize> + Send + 'a
    where
        Self: 'a;
    fn get<'a>(&'a self) -> Self::Ret<'a>
    where
        Self: 'a;
}

impl Get for usize {
    type Ret<'a> = impl Future<Output = usize> + Send + 'a
    where
        Self: 'a;

    fn get<'a>(&'a self) -> Self::Ret<'a>
    where
        Self: 'a,
    {
        async move { *self }
    }
}

fn is_send<R, F: Future<Output = R> + Send>(_f: &F) -> bool {
    true
}

async fn wrap<G: Get>(g: &G) -> usize {
    let fut = g.get();
    assert!(is_send(&fut));
    fut.await
}

async fn wrap_wrap<G: Get>(g: &G) -> usize {
    let fut = wrap(g);
    assert!(is_send(&fut)); //~ ERROR the parameter type `G` may not live long enough
    fut.await
}

I expected to see no compiler errors: the returned Future from async fn wrap should be Send, because g.get() is Send and async fn wrap only wraps the code in an asynchronous code block.

Instead, this happened: the returned Future from async fn wrap is not anymore Send. Note that the error manifests differently if another lifetime bounds are involved in the trait - lifetime bound not satisfied when asserting is_send(&fut). It's even strange to see lifetime bounds or may not live long enough errors when checking the Send bound.

Meta

rustc --version --verbose:

rustc 1.59.0 (9d1b2106e 2022-02-23)
binary: rustc
commit-hash: 9d1b2106e23b1abd32fce1f17267604a5102f57a
commit-date: 2022-02-23
host: aarch64-apple-darwin
release: 1.59.0
LLVM version: 13.0.0
Error

error[E0311]: the parameter type `G` may not live long enough
   --> tests/test.rs:687:17
    |
684 |     async fn wrap_wrap<G: Get>(g: &G) -> usize {
    |                        -- help: consider adding an explicit lifetime bound...: `G: 'a +`
...
687 |         assert!(is_send(&fut));
    |                 ^^^^^^^ ...so that the type `G` will meet its required lifetime bounds...
    |
note: ...that is required by this bound
   --> tests/test.rs:674:43
    |
674 |     fn is_send<R, F: Future<Output = R> + Send>(_f: &F) -> bool {
    |                                           ^^^^

error: could not compile `async-trait` due to previous error

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-GATsArea: Generic associated types (GATs)A-async-awaitArea: Async & AwaitA-lifetimesArea: Lifetimes / regionsA-trait-systemArea: Trait systemAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.F-impl_trait_in_assoc_type`#![feature(impl_trait_in_assoc_type)]`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.WG-asyncWorking group: Async & await

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions