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

Borrowing from arguments with higher order async functions #66198

Closed
madmaxio opened this issue Nov 7, 2019 · 3 comments

Comments

@madmaxio
Copy link

@madmaxio madmaxio commented Nov 7, 2019

Hi, just wanted to ask if borrow with higher order async fns (from there arguments) is not correct never at all, or there might be some solutions in the future. Please check the example.

use std::future::Future;

async fn f(data: &Vec<String>) {
    
}

async fn start<Fut>(prm: fn(&Vec<String>) -> Fut) 
where
    Fut: Future<Output = ()>
{
    let data = vec![];
    prm(&data).await;
}

fn main() {
    start(f);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/main.rs:16:11
   |
16 |     start(f);
   |           ^ expected concrete lifetime, found bound lifetime parameter
   |
   = note: expected type `for<'r> fn(&'r std::vec::Vec<std::string::String>) -> _`
              found type `for<'_> fn(&std::vec::Vec<std::string::String>) -> impl std::future::Future {f}`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

@cramertj

This comment has been minimized.

Copy link
Member

@cramertj cramertj commented Nov 7, 2019

start only accepts a single type Fut, yet the type returned from async fn f is dependent upon the lifetime of the data parameter.

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

@nikomatsakis nikomatsakis commented Nov 12, 2019

This example is indeed behaving as expected. The problem here, @madmaxio, is maybe more clear if we expand the signature:

async fn start<Fut>(prm: for<'a> fn(&'a Vec<String>) -> Fut) 

Here the problem is that the argument lifetime ('a) is not in scope for the type Fut, so it can't be part of that type. You could refactor this to:

async fn start<'a, Fut>(prm: fn(&'a Vec<String>) -> Fut) 

but that might not work well with the overall design. I'm going to close the issue, in any case, as "working as intended", and suggest you take the example to users.rust-lang.org to try and get more feedback on how best to fix it. :)

@madmaxio

This comment has been minimized.

Copy link
Author

@madmaxio madmaxio commented Nov 12, 2019

Thank you guys for the reply. I'm passing parameter by move now. Makes sense borrowing is not allowed here.

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