2

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.

Uraty
  • 257
  • 2
  • 7
  • 1
    Possibly a duplicate of [this question](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct) which has an excellent answer – myrtlecat Aug 18 '20 at 11:00
  • I saw that question. Looks similar but I think it's not exactly this situation: I have different error, and referenced objects is stored in the heap rather than in stack as in suggested answer. – Uraty Aug 18 '20 at 11:04
  • 1
    I was actually just editing my comment to say I see that you have a different error, so maybe it is not the same. – myrtlecat Aug 18 '20 at 11:04
  • 1
    The linked answer specifically deals with how to work around the "overzealous" borrow-checker when your values are on the heap – myrtlecat Aug 18 '20 at 11:38

1 Answers1

1

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.

myrtlecat
  • 2,156
  • 12
  • 16