Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why I cannot define a Simple Struct with Safe + Send features enabled

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading