Skip to content

Commit 84ae95b

Browse files
committed
Refactored macro to change nightly-cfg behavior pre-expansion.
This is a breaking change.
1 parent bdd5fdd commit 84ae95b

File tree

3 files changed

+78
-42
lines changed

3 files changed

+78
-42
lines changed

src/lazy.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use std::sync::Once;
2+
3+
pub struct Lazy<T: Sync>(pub *const T, pub Once);
4+
5+
impl<T: Sync> Lazy<T> {
6+
#[inline(always)]
7+
pub fn get<F>(&'static mut self, f: F) -> &T
8+
where F: FnOnce() -> T
9+
{
10+
unsafe {
11+
let r = &mut self.0;
12+
self.1.call_once(|| {
13+
*r = Box::into_raw(Box::new(f()));
14+
});
15+
16+
&*self.0
17+
}
18+
}
19+
}
20+
21+
unsafe impl<T: Sync> Sync for Lazy<T> {}
22+
23+
#[macro_export]
24+
macro_rules! lazy_static_create {
25+
($NAME:ident, $T:ty) => {
26+
use std::sync::ONCE_INIT;
27+
static mut $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy(0 as *const $T, ONCE_INIT);
28+
}
29+
}

src/lib.rs

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,13 @@ The `Deref` implementation uses a hidden static variable that is guarded by a at
6969
*/
7070

7171
#![cfg_attr(feature="nightly", feature(const_fn, core_intrinsics))]
72-
#![crate_type = "dylib"]
72+
73+
#[cfg(not(feature="nightly"))]
74+
pub mod lazy;
75+
76+
#[cfg(feature="nightly")]
77+
#[path="nightly_lazy.rs"]
78+
pub mod lazy;
7379

7480
#[macro_export]
7581
macro_rules! lazy_static {
@@ -84,52 +90,15 @@ macro_rules! lazy_static {
8490
impl ::std::ops::Deref for $N {
8591
type Target = $T;
8692
fn deref<'a>(&'a self) -> &'a $T {
87-
#[inline(always)]
88-
fn __static_ref_initialize() -> $T { $e }
89-
9093
unsafe {
91-
use std::sync::{Once, ONCE_INIT};
92-
93-
#[inline(always)]
94-
fn require_sync<T: Sync>(_: &T) { }
95-
9694
#[inline(always)]
97-
#[cfg(feature="nightly")]
98-
unsafe fn __stability() -> &'static $T {
99-
use std::cell::UnsafeCell;
100-
101-
struct SyncCell(UnsafeCell<Option<$T>>);
102-
unsafe impl Sync for SyncCell {}
103-
104-
static DATA: SyncCell = SyncCell(UnsafeCell::new(None));
105-
static ONCE: Once = ONCE_INIT;
106-
ONCE.call_once(|| {
107-
*DATA.0.get() = Some(__static_ref_initialize());
108-
});
109-
match *DATA.0.get() {
110-
Some(ref x) => x,
111-
None => ::std::intrinsics::unreachable(),
112-
}
113-
}
95+
fn __static_ref_initialize() -> $T { $e }
11496

115-
#[inline(always)]
116-
#[cfg(not(feature="nightly"))]
11797
unsafe fn __stability() -> &'static $T {
118-
use std::mem::transmute;
119-
use std::boxed::Box;
120-
121-
static mut DATA: *const $T = 0 as *const $T;
122-
static mut ONCE: Once = ONCE_INIT;
123-
ONCE.call_once(|| {
124-
DATA = transmute::<Box<$T>, *const $T>(
125-
Box::new(__static_ref_initialize()));
126-
});
127-
&*DATA
98+
lazy_static_create!(LAZY, $T);
99+
LAZY.get(__static_ref_initialize)
128100
}
129-
130-
let static_ref = __stability();
131-
require_sync(static_ref);
132-
static_ref
101+
__stability()
133102
}
134103
}
135104
}

src/nightly_lazy.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use std::sync::Once;
2+
3+
use std::cell::UnsafeCell;
4+
use std::sync::ONCE_INIT;
5+
6+
pub struct Lazy<T: Sync>(UnsafeCell<Option<T>>, Once);
7+
8+
impl<T: Sync> Lazy<T> {
9+
#[inline(always)]
10+
pub const fn new() -> Self {
11+
Lazy(UnsafeCell::new(None), ONCE_INIT)
12+
}
13+
14+
#[inline(always)]
15+
pub fn get<F>(&'static self, f: F) -> &T
16+
where F: FnOnce() -> T
17+
{
18+
unsafe {
19+
self.1.call_once(|| {
20+
*self.0.get() = Some(f());
21+
});
22+
23+
match *self.0.get() {
24+
Some(ref x) => x,
25+
None => ::std::intrinsics::unreachable(),
26+
}
27+
}
28+
}
29+
}
30+
31+
unsafe impl<T: Sync> Sync for Lazy<T> {}
32+
33+
#[macro_export]
34+
macro_rules! lazy_static_create {
35+
($NAME:ident, $T:ty) => {
36+
static $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy::new();
37+
}
38+
}

0 commit comments

Comments
 (0)