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

"expected bound lifetime parameter, found concrete lifetime" when passing a 'static reference to a closure that returns a future #68521

Open
shepmaster opened this issue Jan 24, 2020 · 1 comment
Labels
A-async-await Area: Async & Await A-closures Area: closures (`|args| { .. }`) A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@shepmaster
Copy link
Member

shepmaster commented Jan 24, 2020

use std::future::Future;

fn main() {
    let _ = wrapper(hello);
}

static GLOBAL: i32 = 42;

async fn wrapper<F, FutResp>(f: F)
where
    F: Fn(&i32) -> FutResp,
    FutResp: Future<Output = ()>,
{
    f(&GLOBAL).await
}

async fn hello(_: &i32) {
    println!("Hello");
}

(Playground)

Errors:

error[E0271]: type mismatch resolving `for<'r> <for<'_> fn(&i32) -> impl std::future::Future {hello} as std::ops::FnOnce<(&'r i32,)>>::Output == _`
  --> src/main.rs:4:13
   |
4  |     let _ = wrapper(hello);
   |             ^^^^^^^ expected bound lifetime parameter, found concrete lifetime
...
9  | async fn wrapper<F, FutResp>(f: F)
   |          -------
10 | where
11 |     F: Fn(&i32) -> FutResp,
   |                    ------- required by this bound in `wrapper`

I can make the code work by restricting the closure to only accept 'static references:

async fn wrapper<F, FutResp>(f: F)
where
    F: Fn(&'static i32) -> FutResp,
    //     ^^^^^^^
    FutResp: Future<Output = ()>,

I did try to add 'static bounds to the response future (and the closure, for good measure), but this did not help:

async fn wrapper<F, FutResp>(f: F)
where
    F: Fn(&i32) -> FutResp + 'static,
    FutResp: Future<Output = ()> + 'static,

The equivalent(?) synchronous code works as I'd expect:

fn main() {
    let _ = wrapper(hello);
}

static GLOBAL: i32 = 42;

fn wrapper<F>(f: F)
where
    F: Fn(&i32) -> (),
{
    f(&GLOBAL)
}

fn hello(_: &i32) {
    println!("Hello");
}
@jonas-schievink jonas-schievink added A-async-await Area: Async & Await A-closures Area: closures (`|args| { .. }`) A-lifetimes Area: lifetime related C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 24, 2020
@Aaron1011
Copy link
Member

Aaron1011 commented Jan 25, 2020

Adding an explicit lifetime 'a allows this to compile:

use std::future::Future;

fn main() {
    let _ = wrapper(hello);
}

static GLOBAL: i32 = 42;

async fn wrapper<'a, F, FutResp>(f: F)
where
    F: Fn(&'a i32) -> FutResp + 'a,
    FutResp: Future<Output = ()>,
{
    f(&GLOBAL).await
}

async fn hello(_: &i32) {
    println!("Hello");
}

I think the issue is that F: Fn(&i32) -> FutResp requires FutResp to be 'static (or at least, not dependent on the lifetime of the &i32. However, the future returned by async fn hello(_: &i32) does depend on the lifetime of the &i32, since the &i32 can be used within the generator.

However, the error message is almost completely opaque. We should probably add some special-casing around lifetime-related errors when async functions are involved.

@jonas-schievink jonas-schievink added the A-diagnostics Area: Messages for errors, warnings, and lints label Jan 25, 2020
@tmandry tmandry added AsyncAwait-OnDeck AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. labels Jan 28, 2020
@tmandry tmandry added the P-medium Medium priority label Mar 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await A-closures Area: closures (`|args| { .. }`) A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants