Lifetime/Hashmap problem. What's wrong with this code? [SOLVED]

#![allow(warnings,unused)]
use std::collections::HashMap;

#[derive(PartialEq, Eq, Hash)]
enum Data{ Junk, Gunk }

struct Stuff { data: Data }

struct GameState<'key> {
    map: HashMap::<&'key Data, i32>,
    stuff: Stuff,
}
fn load<'key>(map: &mut HashMap::<&'key Data, i32>, stuff: &'key mut Stuff, key: Data) {
    stuff.data = key;
    map.insert(&stuff.data, 99);
}
impl <'key> GameState::<'key> {
    fn new() -> GameState::<'key> {
        let mut map: HashMap::<&'key Data, i32> = HashMap::new();
        let mut stuff = Stuff{ data: Data::Junk};
        GameState{ map,stuff }
    }
    fn update(&mut self) {
        load(&mut self.map, &mut self.stuff, Data::Gunk); //error occurs here
        /*
        I want `stuff` to own the key, and I want `map` to borrow the key.
        - Is this a good way to use hashmap with other data?
        - How/can I do ownership/lifetimes with just 1 key?
        - Should I just make copies of the key instead?
        */
    }
}
fn main() {
    let gs = GameState::new();
    // ...
}

(Playground)

You're not storing hashmap's keys anywhere. It's not possible for a temporary borrow (like &'key) to exist without the referenced data having some storage location that is permanent enough to outlive all uses of GameState<'key>. Rust's references don't store data.

struct GameState<'key> says it's a temporary struct that only has a view of data that has been created and already exists somewhere else, and where that is is pointed to by the 'key lifetime.

In short: don't put references in structs. Use owned types. HashMap<Data, i32>. If you want to store the data by reference, then use HashMap<Box<Data>, i32>.

Box<T> stores data by reference, &T references data without storing it. If data is not stored, you can't reference it.

Wouldn't 2 copies of a hashmap key be a bad thing? If I need to key-in to map data, both the map and another struct will have the same key, and when new data is created, a clone/copy must be made. That's ok?

"You're not storing hashmap's keys anywhere."
hashmap's keys in this example would be stored in stuff, which is in Gamestate.

If you want to share the data between two structs without copying it, then use owned shared reference: Arc<Data>.

& is for temporary scope-limited access only. If you try to use it for things that live longer than a single function call, it will be either very difficult or outright impossible.

& is not a general-purpose reference, it's a very specific very limited kind of reference. It implies things are temporary, immutable, umoveable. Everything that touches it is infected with a lifetime that makes everything else tied to the same scope.

Box and Arc are also a kind of a pointer, hold data by reference, but can live as long as they need, and don't have these limitations.

1 Like

Alright, thank you. i'll do some reading on Arc and see what I can do.

Yeah, I was getting some wacky errors for awhile!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.