0

In my program I have a system where there is a list of objects, each of which stores a list of objects. (Kind of like a tree). Whenever these objects need to update a function is run that recursively goes through all the lists. It looks a bit like this:

struct Object {
  objects: Vec<Object>
}

impl Object {
  fn update(&mut self, parent: &mut Object) {
    for object in self.objects.iter_mut() {
      object.update(self);
    }
  }
}

However, the rust borrow checker prevents this:

35 |         for object in self.objects.iter_mut()  { // Loop through each sub object
   |                       ---------------------------
   |                       |
   |                       first mutable borrow occurs here
   |                       first borrow later used here
36 |             object.update(self); // Update it
   |                         

What would be the preferred way to do this. If you think this is an XY problem please tell me.

EDIT: The objects need their parents for accessing some of the other parameters. (Not shown here)

Boiethios
  • 38,438
  • 19
  • 134
  • 183
TheProff
  • 15
  • 1
  • 6
  • `parent` isn't used in your code... – Boiethios Dec 13 '19 at 08:23
  • This isn't the full code, it is used, but the rest of update is really long. I'd rather not put it all here – TheProff Dec 13 '19 at 08:31
  • In this situation, the issue is that you mutably borrow `self` once (while iterating its objects) and another time when you pass it as `parent`. My piece of advice, as stated in an answer of the linked question, is to use an arena to allocate the objects. – Boiethios Dec 13 '19 at 08:48

1 Answers1

0

In your case a solution depends very much on what you are doing to parent. I find that it often helps to be more explicit about what precisely will be mutated. So, for example, if you want to count the total number of children (and children of children) for an Object while also accessing, say, the parent's name you could do it like this:

struct Object {
    objects: Vec<Object>,
    counter: u32,
    name: String
}

impl Object {
    fn update(&mut self, parent_name: &str) -> u32 {

        for object in self.objects.iter_mut() {
            self.counter += object.update(&self.name);
        }

        // Do something with parent's name, e.g.:
        println!("My parent's name is {}", parent_name);

        self.counter
    }
}

This code compiles because self is only mutated after objectis mutated. So, my suggestion is to think about what you are doing to parent and find a way how you could separate this mutation from the mutations of the children (i.e. objects). Also, to read the parent's parameters you could just pass to update what you need. In my example, this is the parent's name.

joarfish
  • 334
  • 1
  • 10
  • The sub objects need to be able to modify and access parameters of their parents. – TheProff Dec 13 '19 at 09:44
  • Yes, and in my example such a modification of a sub-object's parent is separated from the mutation of the sub-object. – joarfish Dec 13 '19 at 09:50
  • Oh yeah. Sorry I misunderstood your example. You're suggesting that I pass the parameters back. This makes sense, thank you! – TheProff Dec 13 '19 at 09:52