Consuming lifetime problem


I've been fighting with this issue for some time and would really appreciate some help. I'm trying to fully understand the lifetime issues here.

The example code is here: Rust Playground

It's a bit longer but the gist of this is that the result should be a toy linker that owns its inputs (think object files) and have a "collection of views" that refer to the input data in the "output" field for processing along the way. The output just holds "pointers" to the various inputs in some way that makes the job easy. The origin data is never meant to be mutated itself.

The idea here is to try and consume the whole thing at the end as well since once the output is done (and the linker too) the state would be invalid so as to avoid misuse.

The code works as-is if the self-consuming part is not done. E.g. if finalize is not called on the output/linker and instead just &mut self is being used with the 'data lifetime.

Is this a lifetime issue, or is the problem simply that inputs get dropped possibly before the output?

The real thing is even more complicated by the fact that OneInput and OneOutput would be hidden behind traits/generics but this lifetime issue seems to not care about that part.

As implemented, you're basically trying to create a self-referential struct. Now, as implemented, it's true you don't actually create references to yourself until the Linker::link function is called, and self is being consumed. However, at this point, the lifetime of Linker::output has already been tied to that of self, as the compiler message says. It must be, as per the definition of Linker. So even if you deconstructed self and tried to reuse the output that was inside self, its lifetime is going to be problematic.

Is this how your actual program flows? If so, you can just not tie the lifetimes together by not creating the OneOutput until you link(). In this version, the OneOutput lifetime need only live until the call to finalize(), no matter what the Linker lifetime is. (You could have the same result by just creating a new OneOutput in link(), but I didn't see a reason to keep carrying one around inside the Linker/DelayedLinker.)