Skip to content

closures with async blocks have concrete argument lifetimes #59337

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.

Activity

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

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