Error with lifetimes on impl Fn

Hi all, I am trying to get this toy snippet of code to build, but am not able to figure out the lifetime issue and how to solve it.

Probably the lifetime 'a is being used to borrow line in the method split_ascii_whitespace and because 'a spans the whole method, compiler is complaining that line is borrowed for whole of a but does not live that long.

But how do I get past this issue? How do I indicate here that the return reference from the extractor function does not need to live more than the inputs to that function.

fn test<'a>(extractor: impl Fn(&Vec<&'a str>) -> &'a str) {
    let line = String::from("few words in a sentence");
    let parts = line.split_ascii_whitespace().collect::<Vec<_>>();
    println!("{}", extractor(&parts));
    println!("{}", extractor(&parts));
}

fn test<'b>(extractor: impl for<'a> Fn(&Vec<&'a str>) -> &'b str) {
    let line = String::from("few words in a sentence");
    let parts = line.split_ascii_whitespace().collect::<Vec<_>>();
    println!("{}", extractor(&parts));
    println!("{}", extractor(&parts));
}

This compiles. You should use higher-rank trait bounds (HRTBs) on this one to allow the lifetime 'a be relative to the scope for the function extractor rather than relative to test

4 Likes

Wow, that was quick! Thank you so much.
I guess is time to learn something that I had been putting away thinking it to be rarely used stuff (HRTB) :slight_smile:

1 Like

Although right (and good to know), you can elide the lifetime:

fn test<'b>(extractor: impl Fn(&Vec<&str>) -> &'b str) {
    let line = String::from("few words in a sentence");
    let parts = line.split_ascii_whitespace().collect::<Vec<_>>();
    println!("{}", extractor(&parts));
    println!("{}", extractor(&parts));
}

In fact, even your version elides a lifetime: The desuagred version is,

fn test<'b>(extractor: impl for<'a, 'c> Fn(&'c Vec<&'a str>) -> &'b str) {
    let line = String::from("few words in a sentence");
    let parts = line.split_ascii_whitespace().collect::<Vec<_>>();
    println!("{}", extractor(&parts));
    println!("{}", extractor(&parts));
}