error[E0597]: `self` does not live long enough
--> dice_engine/src/renderer/allocator/block_allocator/mod.rs:14:17
|
13 | Box::new(|x| {
| - --- value captured here
| _____________|
| |
14 | | self.echo();
| | ^^^^ borrowed value does not live long enough
15 | | }),
| |______________- cast requires that `self` is borrowed for `'static`
16 | )
17 | }
| - `self` dropped here while still borrowed
I don't understand why self is dropped at the end of the function since it has static lifetime, and what's more, if I copy this code to a brand-new project, it will compile.
So what did I do wrong?
P.S. The reason why I don't use Arc<Self> is that in the real case I do need to modify something by referring to a mut self, and Arc<Mutex<Self>> is not allowed.
Lifetimes do not control how long something lives, rather your code structure (where does it go out of scope and so on) controls that. Lifetimes are claims about how long it lives for, and the compiler will check whether they match with the code structure.
To fix this, you must fix the code structure so that it doesn't go out of scope. You can do this using Box::leak(Box::new(val)) to prevent it from being destroyed.
A better option is to not use static here at all. You should probably be using an Arc or Rc instead of a static reference.
But I guess that where there's a static foo or not will not affect the checking of function allocate, can you explain more (and why it compiles in other projects)?
Aha, I did not understand that you had it in a global. However, the mutex is a problem. A lifetime is actually the duration of the borrow, not how long it lives for. You are only allowed to borrow it for as long as the mutex is locked for, so the only way to get a static reference is to lock it forever, which you don't want.
However, you can get a static reference to the mutex itself.
The reason why I don't use Arc<Self> is that in the real case I do need to modify something by referring to a mut self, and Arc<Mutex<Self>> is not allowed.
That error message means that you are unable to create a &'static Self because you are not actually able to create a borrow of self that lasts until the program ends.
&'static mut self is the worst combination of the two most awful footguns in Rust. It's a complete dead-end, and there's no hope making it work.
&'static mut is a never-ending exclusive access to leaked memory. Such type very rarely has any legitimate use because:
it's leaked, and if you have something like an event handling system you don't want to be leaking all the time
it's strictly exclusive — forever — so it can't be shared between multiple objects, which in case of event handlers is also a very awkward limitation. If you can actually make them work with an exclusively owned object, then a regular Box will work too, and not leak.
When you combine &'static mut with self you get a method that can be called only once ever[1]:
When the compiler tells you to use &'static consider it an invalid suggestion. What it's really trying to say is that in this context all temporary references are forbidden, and can't be made to work. You really really really have to use Arc or some other approach that doesn't involve references. If you need to mutate data behind Arc, you need to add Mutex or atomics.
For callbacks you will need to use for<'a> FnMut(&'a T) syntax. This for<'a> allows you to pass objects temporarily to them (necessary to pass things locked by a Mutex) instead of tying them to some way-too-long lifetime of the outer object or trait.
unless you return self from the method and use the returned object, but that's not a practical solution here ↩︎
There's some sort of disconnect between the example code (which compiles) and the error you pasted. I would expect the method to be problematic to use ala @kornel's example, but not to emit an error about the body of the method. Do you have a more complete example of the error-emitting code?