Skip to content

closures with async blocks have concrete argument lifetimes #59337

@Nemo157

Description

@Nemo157
#![feature(async_await, futures_api)]

use std::future::Future;

trait Foo<'a> {
    type Future: Future<Output = u8> + 'a;

    fn start(self, f: &'a u8) -> Self::Future;
}

impl<'a, Fn, Fut> Foo<'a> for Fn
where
    Fn: FnOnce(&'a u8) -> Fut,
    Fut: Future<Output = u8> + 'a,
{
    type Future = Fut;

    fn start(self, f: &'a u8) -> Self::Future { (self)(f) }
}

fn foo<F>(f: F) where F: for<'a> Foo<'a> {
    let bar = 5;
    f.start(&bar);
}

fn main() {
    foo(async move | f: &u8 | { *f });

    foo({ async fn baz(f: &u8) -> u8 { *f } baz });
}

(playground) currently errors with

(updated playground (with 2021 ed)) currently errors with:

error: implementation of `Foo` is not general enough
  --> src/main.rs:27:5
   |
27 |     foo(async move | f: &u8 | { *f });
   |     ^^^
   |
   = note: Due to a where-clause on `foo`,
   = note: `Foo<'1>` would have to be implemented for the type `[closure@src/main.rs:27:9: 27:37]`, for any lifetime `'1`
   = note: but `Foo<'_>` is actually implemented for the type `[closure@src/main.rs:27:9: 27:37]`, for some specific lifetime `'2`

You can see that the async fn correctly satisfies the HRLB required by foo, but the async closure has a concrete lifetime for the argument instead of being for any lifetime.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.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