It's unclear to me how to fix this even with the nice borrow checker messages.
Here's the simplified code that produces the error:
use std::collections::HashMap;
pub struct X<'a> {
pub a: i32,
pub b: &'a mut i32,
}
impl<'a> X<'a> {
pub fn new(a: i32, b: &'a mut i32) -> X<'a>{
X { a, b}
}
}
pub fn change_hashmap(hashmap_to_change: &mut HashMap<i32, X>) {
let mut c = 2;
let d = 1;
let x = X::new(d, &mut c);
hashmap_to_change.insert(d, x);
}
pub fn main() {
let mut hashmap1: HashMap<i32, X> = HashMap::new();
change_hashmap(&mut hashmap1);
}
Compiling playground v0.0.1 (/playground)
error[E0597]: `c` does not live long enough
--> src/main.rs:17:26
|
13 | pub fn change_hashmap(hashmap_to_change: &mut HashMap<i32, X>) {
| ----------------- has type `&mut std::collections::HashMap<i32, X<'1>>`
...
17 | let x = X::new(d, &mut c);
| ^^^^^^ borrowed value does not live long enough
18 |
19 | hashmap_to_change.insert(d, x);
| ------------------------------ argument requires that `c` is borrowed for `'1`
20 | }
| - `c` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
I'm no expert but I can try.
X has a borrow of c that dies at the end of the function, The hashmap owns X and it lives even after the function ends then your X will have a dangling pointer and because of that it does not compile.
In other word, the error is because hashmap has X who borrows data and needs it to live at least the what X lives but it doesn't because is cleaned after the function ends meanwhile X keep existing as a part of the Hashmap. If you want to solve that make c live at least or longer that X (for example here create c outside and pass it to the function)
Sometimes writing out the lifetimes and types explicity can help clarify things. In this case:
The problem you have is that you’re trying to store a reference to a local variable (c) into a type tagged with a lifetime that lives longer than the function (X<'b>)— as soon as the function returns, there’s no value to reference.
If c needs to be generated by change_hashmap, you’ll need to store it somewhere it can live after the function returns. The simplest choice is to make X.b an i32 instead of a reference.
If you can’t change the X structure for some reason, you’ll need to get the &mut reference from somewhere that lives longer than the HashMap, like the function that owns it.
Just to confirm, @PatatasDelPapa's analysis is correct. Your x does not have ownership of c, but x lives until after the end of the function, which c does not, hence the lifetime error.