Reference to the field in the same/containing structure

Viewed 184

I've created this simple example to simulate what happens with references in my program.

struct Child {}

struct Parent<'a> {
    child: &'a Child
}

struct Family {
    child: Box<Child>,
    parents: Vec<Box<dyn Any>>
}

fn main() {
    let child = Box::new(Child {});
    let mut family = Family { child, parents: vec![] }; // child was moved to the family

    let parent = Box::new(Parent { child: &family.child }); // Parent accepts reference to family's child

    family.parents.push(parent); // Now parent was moved to the family.
    // So Family owns both: child and parent, 
    // so reference to the child in the parent will be correct during
    // lifetime of family
}

This code looks correct for me because the Family owns both: Child and Parent, so they will be dropped at the same time and the Parent can safely hold a reference to the child. But rust compiler doesn't think so:

error[E0597]: `family.child` does not live long enough
   |
18 |     let parent = Box::new(Parent { child: &family.child }); // Parent accepts reference to family's child
   |                                           ^^^^^^^^^^^^^ borrowed value does not live long enough
19 | 
20 |     family.parents.push(parent); // Now
   |                         ------ cast requires that `family.child` is borrowed for `'static`
21 | }
   | - `family.child` dropped here while still borrowed

Usage of dyn Any and boxes is intentional - it simulates what happens in my program.

1 Answers

You appear to have two unrelated issues:

1. Parent does not implement dyn Any

Despite the name, not every type implements the Any trait, as explained in the std::any documentation:

Most types implement Any. However, any type which contains a non-'static reference does not.

So your Parent struct cannot implement Any (unless it is restricted to only have 'static children). As you say the dyn Any comes from the rest of your program, it is difficult to advise a fix.

2. Storing a value and a reference to that value in the same struct

This has been asked before and there is a truly excellent answer.

The usual problem with self-referential structs is that they cannot be moved without invalidating the references.

However, in some cases we can move a self-referential struct safely, such as when the referred-to values are Boxed (as in your Family) provided that the boxed values are never moved. The linked-to answer covers this case and lists possible workarounds.

Related