0

I need to access and modify a static variable:

mod my_mod {
    use std::collections::HashMap;

    pub enum MyA<'a> {
        Instance(&'a MyC<'a>),
        Another,
    }

    pub struct MyC<'a> {
        field: &'a str,
    }

    pub struct MyB<'a> {
        map: HashMap<i32, MyC<'a>>,
    }
    impl<'a> MyB<'a> {
        pub fn new() -> Self {
            MyB {
                map: HashMap::new(),
            }
        }
        pub fn insert<'b: 'a>(&'b mut self, k: i32) -> MyA {
            let v = MyC { field: "hello" };
            self.map.insert(k, v);
            MyA::Instance(self.map.get(&k).unwrap())
        }
    }
}

use crate::my_mod::{MyA, MyB};
use once_cell::sync::Lazy;
use std::sync::Mutex;

static MYB: Lazy<Mutex<MyB>> = Lazy::new(|| Mutex::new(MyB::new()));

fn my_func() -> i32 {
    let mut my_b = MYB.lock().unwrap();
    let my_a = { my_b.insert(1) };
    match my_a {
        MyA::Instance(s) => 1,
        MyA::Another => 2,
    }
}

fn main() {
    my_func();
}

My dependencies:

[dependencies]
once_cell = "1.8.0"

The error:

error[E0597]: `my_b` does not live long enough
  --> src/main.rs:38:18
   |
38 |     let my_a = { my_b.insert(1) };
   |                  ^^^^----------
   |                  |
   |                  borrowed value does not live long enough
   |                  argument requires that `my_b` is borrowed for `'static`
...
43 | }
   | - `my_b` dropped here while still borrowed

It tells me that my_b is dropped at the end of my_func but the reference needs to be valid for the whole program run, if that is what 'static means. Why does it have to be valid for 'static? Is it a problem with lifetime parameters?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
elsamuray7
  • 79
  • 1
  • 10

1 Answers1

1

Remove the incorrect lifetime annotations on MyB::insert:

fn insert(&mut self, k: i32)

When you say insert<'b: 'a>(&'b mut self, that means that 'b outlives 'a.

In your case, my_b is a MutexGuard. When you call insert, you dereference the guard and so &'b self has lifetime of the mutex guard. You are attempting to store a 'static string into the map, so 'a is 'static. The guard does not outlive 'static.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • So there would be a difference if `MyC::field` was not a string literal but a reference to something with a non-static lifetime? Maybe my example was not hundered percent matching with the original code then. Thanks anyway, still helped me a lot! – elsamuray7 Aug 04 '21 at 13:49