Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async closures have concrete argument lifetimes #59337

Open
Nemo157 opened this Issue Mar 21, 2019 · 3 comments

Comments

Projects
None yet
3 participants
@Nemo157
Copy link
Contributor

Nemo157 commented Mar 21, 2019

#![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

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.

@Nemo157

This comment has been minimized.

Copy link
Contributor Author

Nemo157 commented Mar 21, 2019

@rustbot modify labels: A-async-await and T-compiler.

@Nemo157

This comment has been minimized.

Copy link
Contributor Author

Nemo157 commented Mar 21, 2019

Interestingly, using trait aliases instead of the extra trait above gives a different error message, not sure exactly what it believes is wrong here (could easily be a trait alias issue rather than an async closure issue) (playground)

#![feature(async_await, futures_api, trait_alias, unboxed_closures)]

use std::future::Future;

trait Foo<'a> = FnOnce<(&'a u8,)> where <Self as FnOnce<(&'a u8,)>>::Output: Future<Output = u8> + 'a;

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

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

    foo({ async fn baz(f: &u8) -> u8 { *f } baz });
}
error[E0477]: the type `impl std::future::Future` does not fulfill the required lifetime
  --> src/main.rs:13:5
   |
13 |     foo(async move | f: &u8 | { *f });
   |     ^^^
   |
   = note: type must outlive any other region
@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Apr 16, 2019

Marking as deferred since async closures are not considered part of the "core functionality" we are trying to stabilize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.