Lifetime for closure parameter passed to a nested closure

I'm trying to DRY up a piece of code by using a closure, but I can't get the lifetime to work.

Here is a link to an example of what I'm trying to achieve: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2b336614ef6648d00f38166e5ffd5c5c. This is a simplification, in the real code I cannot change the Buffer struct. What I'm trying to get right is the write() function:

fn write<'a, F, T>(buf: Buffer, write_fn: F, val: T)
where
    F: FnOnce(Buffer<'a>, T)
{
    buf.write_with_prefix(1, |buf| {
        write_fn(buf, val); // How do I specify the lifetime of buf?
    })
}

I got this to compile, but I’m not sure why I needed to replace the method reference in main with a closure. If you haven’t run across the for<‘_> syntax before, it basically requires the closure to not keep any references after it returns. (Playground)

fn write<'a, F, T>(buf: Buffer<'a>, write_fn: F, val: T)
where
    F: for<'b> FnOnce(Buffer<'b>, T)
{
    buf.write_with_prefix(1, |buf| {
        write_fn(buf, val);
    })
}

fn main() {
    let buf = Buffer { buf: &mut vec![] };
    write(buf, |b,x| b.write_u32(x), 4);
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=60e8b69351b665a5c33ff5087c8b3ae9

It compiles if I replace Buffer (anonymous lifetime) with Buffer<'a> (that actually matches the lifetime you declare)

1 Like

I noticed that for<'b> is not needed, lifetime elision does the job. Keeping the example as it is and just replacing the method reference with a closure in main works (updated playground). I wonder if it would be possible to make it work with the method reference.

The example I used is a simplified version of the real code I'm trying to get right. I the real code I cannot change the Buffer struct and its implementation.