Method that moves `self` and takes a closure that modifies `self` before it drops?

Here's a stripped-down version of my code that demonstrates the problem.

I'm making a writer API for a serialization format. A Writer<W: Write> can lend a ValueWriter<'a, W> that mutably borrows it. All of the methods of ValueWriter (write_string, write_int, etc) take self by value so it can only be used once.

One of those methods is write_list, which I would also like to take self by value, but it needs to be able to write multiple nested values. I want to achieve this by having write_list take a closure that provides a reusable mutable handle that can write several values.

    .write_list(|list| {

Unfortunately, I can't figure out how to express what I want in a way that the borrow checker understands.

The compiler complains that W doesn't live long enough:

error[E0309]: the parameter type `W` may not live long enough
  --> src/
71 |     type TListWriter<'a> = ListWriter<'a, W>;
   |                            ^^^^^^^^^^^^^^^^^- help: consider adding a where clause: `where W: 'a`
   |                            |
   |                   that the type `W` will meet its required lifetime bounds...
note: ...that is required by this bound
  --> src/
37 |     out: &'a mut W
   |     ^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0309`.
error: could not compile `playground` (bin "playground") due to previous error

It goes on to suggest constraining W, but that isn't possible using HRTB as far as I can tell.

I have also tried constraining type TListWriter<'a> using where Self: 'a, but that only leads to the this compiler error:

error[E0477]: the type `ValueWriter<'value, W>` does not fulfill the required lifetime
  --> src/
73 |     fn write_list<F: for<'a> FnOnce(&mut Self::TListWriter<'a>) -> Result<(), ()>>(
   |        ^^^^^^^^^^

I've tried other things to constrain the HRTB, but frequently bump into this:

due to current limitations in the borrow checker, this implies a `'static` lifetime


This seems to do the trick (line 71):

type TListWriter<'a> = ListWriter<'value, W>;


Thank you very very much. I had chased my tail on this one for quite a while. x_x

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.