5

I'm trying to use a HashMap<String, &Trait> but I have an error message I don't understand. Here's the code (playground):

use std::collections::HashMap;

trait Trait {}

struct Struct;

impl Trait for Struct {}

fn main() {
    let mut map: HashMap<String, &Trait> = HashMap::new();
    let s = Struct;
    map.insert("key".to_string(), &s);
}

Here's the error I'm getting:

error[E0597]: `s` does not live long enough
  --> src/main.rs:12:36
   |
12 |     map.insert("key".to_string(), &s);
   |                                    ^ borrowed value does not live long enough
13 | }
   | - `s` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

What's happening here? Is there a workaround?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
franza
  • 2,297
  • 25
  • 39

1 Answers1

9

This issue was solved with non-lexical lifetimes, and should not be a concern from Rust 2018 onwards. The answer below is relevant for people using older versions of Rust.


map outlives s, so at some point in map's life (just before destruction), s will be invalid. This is solvable by switching their order of construction, and thus of destruction:

let s = Struct;
let mut map: HashMap<String, &Trait> = HashMap::new();
map.insert("key".to_string(), &s);

If you instead want the HashMap to own the references, use owned pointers:

let mut map: HashMap<String, Box<Trait>> = HashMap::new();
let s = Struct;
map.insert("key".to_string(), Box::new(s));
Veedrac
  • 58,273
  • 15
  • 112
  • 169
  • Thanks, that works. But can you please explain why `map` outlives `s`? I thought that variables are destructed at the end of scope, so is there any specific order of destruction? – franza Aug 24 '15 at 00:11
  • 4
    "is there any specific order of destruction" → The opposite to the order of construction, because if you have `let x = 1; let y = T(&x);`, the destructor of `y` might need to access `x`. – Veedrac Aug 24 '15 at 00:16
  • Oh, I see. I think this is because those vars are allocated in stack. – franza Aug 24 '15 at 08:23