Pub static seem to create different "instance" in each dependent crate

Hi there,
I guess I'm not understanding the static concept of Rust in case of how it is treated across crates.

I've created a crate lets name it provider. This crate provides a public static variable:

pub static VARIABLE: SomeType = SomeType::new();

The SomeType here takes care that mutable exclusive access to data and functions of the VARIABLEis guaranteed.
Now I've two different crates that use this one as a dependency. Let's call them consumer-one and consumer-two.

My expectation now was, that either consumer see's always the same static VARIABLE. So if consumer-one does some initialization on this static variable the consumer-two could expect the static variable has performed initialization as well. But I've seen that each crate seem to "instantiate" it's own version of the static VARIABLE. If I print the linker symbols created for the final binary I have confirmed that there are really 2 different symbols for the same static VARIABLE created.

The question now is: Is this function as designed and I do something wrong conceptually are is there a specific trick required to make this staticreally global across the both consumer crates?

That the pub static seem to be a dependent crate local is quite confusing me....

Thanks in advance giving me a clue...
BR

I do not think it is supposed to work that way expect that two different versions of provider would create to different "instances" of the global.

To make sure I whipped up a small diamond to test this:

 .
β”œβ”€β”€ bin-user
β”‚   β”œβ”€β”€ Cargo.toml
β”‚   └── src
β”‚       └── main.rs
β”œβ”€β”€ lib-def
β”‚   β”œβ”€β”€ Cargo.toml
β”‚   └── src
β”‚       └── lib.rs
β”œβ”€β”€ lib-user-a
β”‚   β”œβ”€β”€ Cargo.toml
β”‚   └── src
β”‚       └── lib.rs
└── lib-user-b
    β”œβ”€β”€ Cargo.toml
    └── src
        └── lib.rs

where lib-def does

pub static VARIABLE: AtomicBool = AtomicBool::new(false);

and lib-user-a does

pub fn set_variable() {
    lib_def::VARIABLE.store(true, Ordering::SeqCst);
}

and lib-user-b does

pub fn print_variable() {
    dbg!(lib_def::VARIABLE.load(Ordering::SeqCst));
}

so that bin-user doing

fn main() {
    lib_user_a::set_variable();
    lib_user_b::print_variable();
}

does indeed show

[lib-user-b/src/lib.rs:4] lib_def::VARIABLE.load(Ordering::SeqCst) = true

Could you try to reduce your crates to such a minimal form?

Concerning the versioning issue, you could check your Cargo.lock (manually or via something like cargo-tree) whether indeed two different versions of provider are pulled in.

Thanks for the response and the efforts to reproduce the setup nicely and confirm that it indeed should work as I expect (assuming always the same crate version is factored in). I'll check the versions and try to create a small reproducible setup to see what might be gone wrong ...

That was the right tip. After checking the Cargo.lock I noticed that the "provider" was picked one time from the local drive and one time from the crates.io. Fixed this and now it's exactly as expected :smiley:

Thx a ton.

1 Like