Comment on
Using OnceCell with Regex (for reading only)
So, the error you're getting here is that the static itself needs synchronization, multiple threads can try to initialize the OnceCell at once because this is a static (only one initialization function gets called, the rest have to block).
consider an example like this:
use regex::Regex;
use std::cell::OnceCell;
// this can't compile because of the code below.
static INSTANCE: OnceCell<Regex> = OnceCell::new();
fn main() {
std::thread::spawn(|| {
let foo = INSTANCE.get_or_init(|| Regex::new("abc"));
// something that does something with `foo`
});
// uh-oh, this can happen at the exact same time as the above,
// which is UB if this compiles (we have a data race).
let foo = INSTANCE.get_or_init(|| Regex::new("abc"));
// again something that does something with foo.
}
lazy_static uses a lock under the hood. Specifically, when std is available (when std isn't available I think it uses a spinlock but I didn't actually check) it uses https://doc.rust-lang.org/std/sync/struct.Once.html (not to be confused with OnceCell/OnceLock), which explicitly states it locks. As in the excerpt below:
This method will block the calling thread if another initialization routine is currently running.
The short answer is, yes, you have to use OnceLock if you want this in a static, and OnceLock does roughly what lazy_static does anyway.