This could be a very basic Rust question, I am trying to create a mut static object inside a mod. And to do that I need to implement a Lazy construct but I am not understanding why I cannot create a Lazy construct for my simple struct:
pub struct S {
a_: String,
}
impl S {
pub fn new(a: String) -> Self {
S {
a_: a
}
}
pub fn foo(&self) {
println!("{}", self.a_);
}
}
unsafe impl Sync for S {}
unsafe impl Send for S {}
I am getting errors like:
`error[E0277]: `Cell<Option<fn() -> S>>` cannot be shared between threads safely --> src/main.rs:26:15
| 26 | static X: Lazy<S> = Lazy::new(|| {
| ^^^^^^^ `Cell<Option<fn() -> S>>` cannot be shared between threads safely
|
= help: within `once_cell::unsync::Lazy<S>`, the trait `Sync` is not implemented for `Cell<Option<fn() -> S>>`
= note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` note: required because it appears within the type `Lazy<S>` --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.19.0/src/lib.rs:714:16
| 714 | pub struct Lazy<T, F = fn() -> T> {
| ^^^^
= note: shared static variables must have a type that implements `Sync``
First I tried to define the struct S without the custom impl’s:
unsafe impl Sync for S {}
unsafe impl Send for S {}
But it didn’t work. As in the below code I am adding them back but no results.
fn main() {
let s = s_mod::S::new("10".to_string());
s.foo();
}
mod s_mod {
use once_cell::unsync::Lazy;
pub struct S {
a_: String,
}
impl S {
pub fn new(a: String) -> Self {
S {
a_: a
}
}
pub fn foo(&self) {
println!("{}", self.a_);
}
}
unsafe impl Sync for S {}
unsafe impl Send for S {}
static X: Lazy<S> = Lazy::new(|| {
let s = S::new("4".to_string());
s
});
}
What am I missing here? Can someone help me understand?
>Solution :
once_cell::unsync::Lazy cannot be sent across threads (as implied by the unsync).
You should use once_cell::sync::Lazy instead.
Your struct itself being Sync is insufficient as it is wrapped inside of this type.