"Registering" instances of structs in a vector via constructor

Hi all,

Suppose I have a struct that I want to automatically add a reference to itself in a vector when it is created (and plan on removing the reference when it is dropped) so I can maintain a list of instances to process over at a later time.

struct Collection<'a> {
    items: Vec<&'a Item>,
}

impl Collection<'_> {
    fn new() -> Collection<'static> {
        Collection { items: Vec::new() }
    }
}

struct Item {}

impl Item {
    fn new(collection: &mut Collection) -> Item {
        let new_item = Item {};
        collection.items.push(&new_item);
        new_item
    }
}

fn main() {
    let mut collection = Collection::new();
    let item = Item::new(&mut collection);
}

But the compiler doesn't like this approach.

error[E0597]: `new_item` does not live long enough
  --> src/main.rs:16:31
   |
14 |     fn new(collection: &mut Collection) -> Item {
   |            ---------- has type `&mut Collection<'1>`
15 |         let new_item = Item {};
16 |         collection.items.push(&new_item);
   |         ----------------------^^^^^^^^^-
   |         |                     |
   |         |                     borrowed value does not live long enough
   |         argument requires that `new_item` is borrowed for `'1`
17 |         new_item
18 |     }
   |     - `new_item` dropped here while still borrowed

error[E0505]: cannot move out of `new_item` because it is borrowed
  --> src/main.rs:17:9
   |
14 |     fn new(collection: &mut Collection) -> Item {
   |            ---------- has type `&mut Collection<'1>`
15 |         let new_item = Item {};
16 |         collection.items.push(&new_item);
   |         --------------------------------
   |         |                     |
   |         |                     borrow of `new_item` occurs here
   |         argument requires that `new_item` is borrowed for `'1`
17 |         new_item
   |         ^^^^^^^^ move out of `new_item` occurs here

It seems that I cannot move ownership of a value while there exists a reference to it. At least that's what I think is happening. Any ideas on how I might solve this problem to make the compiler happy with me?

Thanks,
Richard

While an immutable reference exists to a value, it's impossible to move or modify it. You can't do this with references.

1 Like

Ok, thanks Alice. That's what I am learning. I have solved this by pushing the reference in a separate method, not inside the constructor. --Richard

References are typically used for short-term borrows, not long term storage. Details are sparse but you may want to look into storing something like a

  • Rc<Item>
    • Or Rc<Cell<Item>> or Rc<RefCell<Item>>
  • Arc<Item>
    • Or Arc<Mutex<Item>> or Arc<RwLock<Item>>