0

I have a struct that contains a vector of substructs, each requiring some rather large data structure for computations, which may or may not be shared with other substructs. Thus, it makes sense that the superstruct owns these data structures and the substructs only have references. Attempting to write a constructor for this, I'm running into a lifetime error I can't quite decipher.

Minimal non-working example:

use std::collections::HashMap;

struct SuperStruct<'a> {
    hash_map: HashMap<String, Vec<f64>>,
    substructs: Vec<SubStruct<'a>>,
}

impl<'a> SuperStruct<'a> {
    fn new(vectors: Vec<Vec<f64>>) -> SuperStruct<'a> {
        let mut substructs = vec![];
        let mut hash_map = HashMap::new();
        let mut k = 0;

        for vector in vectors {
            substructs.push(SubStruct { reference: &vector });
            hash_map.insert(format!("vec_{}", k), vector);
            k += 1;
        }
        SuperStruct{ hash_map, substructs }
    }
}

struct SubStruct<'a> {
    reference: &'a Vec<f64>,
}

fn main() {
    // println!("Hello");
}

Trying to compile this results in the following error:

error[E0597]: `vector` does not live long enough
  --> moo.rs:15:53
   |
15 |             substructs.push(SubStruct { reference: &vector });
   |                                                     ^^^^^^ does 
not live long enough
...
18 |         }
   |          - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on 
the impl at 8:1...
  --> moo.rs:8:1
   |
8  | / impl<'a> SuperStruct<'a> {
9  | |     fn new(vectors: Vec<Vec<f64>>) -> SuperStruct<'a> {
10 | |         let mut substructs = vec![];
11 | |         let mut hash_map = HashMap::new();
...  |
20 | |     }
21 | | }
   | |_^

I bet I'm missing something really obvious, but what is it?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
sjp
  • 382
  • 4
  • 15
  • `vector` owns a `Vec`. You take a reference to it, but then transfer ownership of `vector` to the `HashMap`. This also changes the address of `vector`, invalidating any references to it. You'll either want to split up `SuperStruct`'s members into two different structures, use `Rc` or `Arc`, or maybe one of the crates like rental or owning_ref. – Shepmaster Nov 24 '17 at 16:51
  • After reading the suggested duplicate (which provided an excellent answer to my original question), I have revised the design and edited the question. – sjp Nov 24 '17 at 17:24
  • Please do not drastically change your question after it has been answered (and a duplicate counts as an answer), especially as you say it "provided an excellent answer to my original question". Duplicates are not a bad thing on Stack Overflow, they serve as signposts for future searchers having the same problem. You are instead welcome to ask another question on a new topic. – Shepmaster Nov 24 '17 at 20:05
  • Fair enough, thanks for undoing the edit. – sjp Nov 24 '17 at 22:30

0 Answers0