I'm trying to model a behavior where a Parent
produces Intermediate
objects that, when finalized, will become Leaf
. I would like to make it so that Parent
is mutably borrowed while working with Intermediate
, thus ensuring there's at most one such objects for each Parent
that I have.
I've been able to do that without problems so far, but it's my last requirement that's making this difficult. I would also like for no Leaf
object to outlive the Parent
it came from. But this doesn't seem possible without immutably borrowing Parent
and preventing any other Intermediate
objects from being created while a Leaf
exists.
I'm posting simplified code below. I tried a more involved solution with another object to place the borrows on (allowing &mut Parent
to exist independently) and then unifying the lifetime of it with Parent
, but that has its own problems.
use std::marker::PhantomData;
struct Parent;
struct Intermediate<'p>(&'p mut Parent);
struct Leaf<'p>(PhantomData<&'p Parent>);
impl Parent {
fn produce<'p>(&'p mut self) -> Intermediate<'p> {
Intermediate(self)
}
}
impl<'p> Intermediate<'p> {
fn finish(self) -> Leaf<'p> {
Leaf(PhantomData)
}
}
fn main() {
let mut parent = Parent;
let intermediate = parent.produce();
let leaf1 = intermediate.finish();
let intermediate = parent.produce();
let leaf2 = intermediate.finish();
// I want this order of destructors
drop(leaf2);
drop(leaf1);
drop(parent);
}
Is there a way to do it without runtime checking & smart pointers?