Learning Lifetime error

I am learning Rust' lifetime, and write some code to understand the topic. But now, I need help,The code will report an error if I uncomment a line in code.

The code follows:

use std::collections::HashMap;

#[derive(Debug)]
pub struct EDocument<'a>{
    tables:Vec<ETable<'a>>,
}

#[derive(Debug)]
pub struct ETable<'b>{
    column_index:HashMap<String, usize>,
    records:Vec<ERecord<'b>>,
}

#[derive(Debug)]
pub struct ERecord<'a>{
    cols:&'a HashMap<String, usize>,
}


fn main(){

    let mut doc = EDocument{tables:Vec::new()};
    for i in 0..10{
        let t = ETable{column_index:HashMap::new(), records:Vec::new()};
        doc.tables.push(t);
    }

    {
        let doc_mut = &mut doc;
        for t in doc_mut.tables.iter_mut(){
            for i in 0..10{
                let r = ERecord{cols:&t.column_index};
                t.records.push(r);  //   ERROR
            }
        }
    }

    for t in doc.tables.iter_mut(){
        t.column_index.insert("xxx".to_string(), 3);
        for i in t.records.iter(){
            println!("{:?}", i);
        }
    }

}

My understanding is t.records.push(r) expands the lifetime range 'a, but I fail to change code to fix the error.
How could I fix it?

You can't, not with normal references. Keep in mind that references are temporary compile time locks, don't use them for anything persistent. Also, you are trying to create a self-referential type, this almost never goes well.

Em, How can I deal with such problems? The Child Struct share Parent field's data or one struct share common data, I have a runnable version is not with references, but it too waste memory and performance that to alloc same data for the field when records amount is large.
In C++, (smile) simply a pointer can deal its. I want to use rust new features to deal with such's problem... e, maybe I need to learn more.

This would be bad in C++ too, what happens when you add new tables to EDocument? You'll get a reallocation and all of the tables move. To handle this in C++ you will either not use pointers or use a move constructor (this is expensive)

The way to solve this in Rust is to use Rc to allow sharing the map between ERecord and ETable

Thank you, I will try it. :smiley:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.