Read vector to use reference during modifying it

Does exist a way to read a vector content during insert values in it ? There is an example :

struct Content<'a> {
    id: i32,
    parent: Option<&'a Content<'a>>,
}

fn main() {
    let source = vec![(1, None), (2, Some(1))];
    let mut contents: Vec<Content> = vec![];

    for (content_id, parent_id) in source {
        let parent = parent_id.and_then(|parent_id| {
            Some(
                contents
                    .iter()
                    .find(|content| content.id == parent_id)
                    .expect("Source content must be correctly ordered"),
            )
        });
        let content = Content {
            id: content_id,
            parent,
        };
        contents.push(content);
    }
}

Which produce :

error[E0502]: cannot borrow `contents` as mutable because it is also borrowed as immutable
  --> src/main.rs:23:9
   |
11 |         let parent = parent_id.and_then(|parent_id| {
   |                                         ----------- immutable borrow occurs here
12 |             Some(
13 |                 contents
   |                 -------- first borrow occurs due to use of `contents` in closure
...
23 |         contents.push(content);
   |         ^^^^^^^^^----^^^^^^^^^
   |         |        |
   |         |        immutable borrow later used by call
   |         mutable borrow occurs here

My goal, is to store in vector/hashmap, a list of object which can have reference to an object in this vector/hashmap. But, I'm not sure about how to achieve that ...

No. You're creating something called a self-referential value. The usual example is when a struct has one field containing a reference to another field of the same struct. However, your example of having one vector element reference another also qualifies. Self-referential values are not possible in Rust.

I recommend using indexes instead of references for this.

Added: To clarify, self-referential values are not possible when using references. There are other smart pointers (e.g. Rc or Arc) where it is possible. However, in this case, I think indexes is a simpler solution.

4 Likes

Okay. I already used indexes method I will use it agin here. Thanks !

Also note that push may cause the Vec to reallocate, making any existing reference dangling. Rust just saved you from a use-after-free bug.

4 Likes