rust-lang-nursery / lazy-static.rs

A small macro for defining lazy evaluated static variables in Rust.
Apache License 2.0
1.9k stars 111 forks source link

Added an implementation of lazy_static without std in stable Rust #122

Closed brunoczim closed 5 years ago

brunoczim commented 5 years ago

Currently, lazy static has an implementation for no_std crates which requires nightly. I have added a new implementation of lazy_static which works on stable Rust.

Question: I have added a new feature and a new implementation. Should we keep it as a new implementation or should we overwrite nightly spin implementation?

KodrAus commented 5 years ago

Hi @brunoczim! :wave:

Before we dig into the code itself are you able to share a bit about how you've found yourself needing it, and how this new implementation works compared to the existing nightly one using spin?

brunoczim commented 5 years ago

Use

Okay. I confess this is not something I need. I don't want to be redundant, but imagine you are writing a Kernel and you do not want to have to use nightly but need to initialize some... lazy static. I mean, you would have to introduce some instability by using nightly.

Some differences

I think the main important is: I did not wrote some generic API shared between all static variables. I wrote inside the __lazy_static_create a specific type for that static. This removes the need of having a const fn.

Another difference is: spin's implementation does not store a T. It stores an Option<T>. I think there is a little overhead on checking Option<T> every time the static is accessed. My implementation used a trick in order not to have this overhead. I used core::mem::size_of to make a byte array with the size of T. I have also used a zero-sized array of T to force alignment.

However, the spinning over the initialization status works in the same way as spin's implementation of Once. I thought they used a Mutex to write Once, but it is more like a RwLock (just like I did). Not sure why the Mutex was in my head, maybe it was like that one day.

I do recognize there is not too much difference. The real reason I implemented this is so we can have a stable API with no_std. Importing it from another crate does not allow us avoiding const fn.

NOTE: the size_of trick only works on non-generic types. This is the one of the reasons I wrote a specific type for each static.

brunoczim commented 5 years ago

Well, there is another option. I was thinking: spin could expose Once::<T>::INIT. This would allow lazy_static to use it on stable.

brunoczim commented 5 years ago

I have had a merged PR on spin which allows Once to be initialized via constant on stable Rust. This custom implementation of lazy_static is not needed anymore. We may simply rewrite the spin version.

KodrAus commented 5 years ago

Thanks for chasing this up @brunoczim! A no-std spin-based implementation that also works on stable sounds great to me :+1:

KodrAus commented 5 years ago

@brunoczim now that https://github.com/mvdnes/spin-rs/pull/55 is merged and released on crates.io would you be interested in refactoring our existing no_std impl to work on stable Rust using spin?

brunoczim commented 5 years ago

Yes I am. Count me in.

brunoczim commented 5 years ago

I am closing this in favor of #130