Is there a way to call methods on static muts? The only workarounds i have found are to either use functions instead of methods or raw pointers.
struct A {
// Holds value that are expensive to clone
val: u64,
}
impl A {
fn get_ref(&self) -> u64 {
self.val
}
fn get_own(self) -> u64 {
self.val
}
fn get_mut(&mut self) -> u64 {
self.val
}
}
static mut HOLD: A = A {val: 0};
fn main() {
unsafe {
// Cant create a refernce to static mut
let a = HOLD.get_ref();
let b = HOLD.get_mut();
// Cant move out of static mut
let c = HOLD.get_own();
// Onyl workaround (Gets marked by clippy)
let d = (*(&raw const HOLD)).get_ref();
let e = (*(&raw mut HOLD)).get_ref();
}
}
fn b() -> u64 {
unsafe {
HOLD.val
}
}
static mut is extremely difficult to use soundly. Outside of some very narrow use cases, you should instead by using a static (without mut) and a type that provides sound interior mutability, such as Mutex or AtomicU64.
use std::sync::atomic;
struct A {
val: atomic::AtomicU64,
}
impl A {
fn get(&self) -> u64 {
self.val.load(atomic::Ordering::Relaxed)
}
}
static HOLD: A = A {val: atomic::AtomicU64::new(0)};
fn main() {
let val = HOLD.get();
}
If you can’t express what you need using an existing type, then you can write your own interior-mutable type (with &self methods!) that uses UnsafeCell internally. Such code needs to be reviewed carefully for soundness.
Stop using static mut and everything will go better. Make it just static HOLD: A instead, and have the appropriate things inside the A (such as a Mutex<u64>) or whatever.
Or just have it be static HOLD: Mutex<A> in the first place.
error[E0507]: cannot move out of static item HOLD
--> src/main.rs:16:11
|
16 | let val = HOLD.get();
| ^^^^ move occurs because HOLD has type A, which does not implement the Copy trait