Force a struct to outlive another struct

Viewed 43

I have two structs. The first, "parent" struct holds a resource that needs explicit cleanup, which I am handling by deriving the Drop trait. The second, "child" struct is retrieved from the parent struct and needs that said resource hasn't been deallocated to be valid.

In other words, any parent instance must outlive its children.

My solution uses references to make the borrow checker enforce this rule.

struct Parent {
    // Private resource data.
}

impl Parent {
    fn new() -> Self {
        Parent {}
    }

    fn new_child(&self) -> Child {
        return Child { _parent: self };
    }
}

impl Drop for Parent {
    fn drop(&mut self) {
        // Do some cleanup after which no instance of Child will be valid.
    }
}

struct Child<'a> {
    _parent: &'a Parent,
    // Private data.
}

impl<'a> Child<'a> {
    fn hello(&self) {
        println!("Hello Child!");
    }
}

fn main() {
    let parent = Parent::new();
    let child = parent.new_child();
    child.hello();

    // Fails to compile with the following line uncommented (as intented).
    // drop(parent);
    // child.hello();
}

This works, but the Child doesn't actually need to know its parent. I thought to replace the reference field with a PhantomData:

struct Child<'a> {
    _parent: PhantomData<&'a Parent>,
    // Private data.
}

But in this case, how can I "bind" _parent to the parent instance, in Parent::new_child?

1 Answers

You could do the following:

struct Parent {
    // Private resource data.
}

struct Child<'a> {
    _parent: PhantomData<&'a Parent>,
    // Private data.
}

impl Parent {
    // The returned child borrows from self
    fn new_child(&self) -> Child<'_> {
        Child { _parent: PhantomData }
    }
}

This should give you the desired behavior.

Related