Skip to content

Commit d14007f

Browse files
committed
Use feature cfg outside macro
cfg(feature="nightly") was being evaluated within the crate using the lazy_static! macro. Instead we generate different macros depending on the cfg. Signed-off-by: Dan Schatzberg <[email protected]>
1 parent bc740c8 commit d14007f

File tree

2 files changed

+81
-41
lines changed

2 files changed

+81
-41
lines changed

src/lazy.rs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use std::sync::Once;
2+
3+
#[cfg(not(feature="nightly"))]
4+
use std::mem::transmute;
5+
#[cfg(feature="nightly")]
6+
use std::cell::UnsafeCell;
7+
#[cfg(feature="nightly")]
8+
use std::sync::ONCE_INIT;
9+
10+
#[cfg(feature="nightly")]
11+
pub struct Lazy<T: Sync>(UnsafeCell<Option<T>>, Once);
12+
13+
#[cfg(not(feature="nightly"))]
14+
pub struct Lazy<T: Sync>(pub *const T, pub Once);
15+
16+
#[cfg(feature="nightly")]
17+
impl<T: Sync> Lazy<T> {
18+
#[inline(always)]
19+
pub const fn new() -> Self {
20+
Lazy(UnsafeCell::new(None), ONCE_INIT)
21+
}
22+
23+
#[inline(always)]
24+
pub fn get<F>(&'static self, f: F) -> &T
25+
where F: FnOnce() -> T
26+
{
27+
unsafe {
28+
self.1.call_once(|| {
29+
*self.0.get() = Some(f());
30+
});
31+
32+
match *self.0.get() {
33+
Some(ref x) => x,
34+
None => ::std::intrinsics::unreachable(),
35+
}
36+
}
37+
}
38+
}
39+
40+
#[cfg(not(feature="nightly"))]
41+
impl<T: Sync> Lazy<T> {
42+
#[inline(always)]
43+
pub fn get<F>(&'static mut self, f: F) -> &T
44+
where F: FnOnce() -> T
45+
{
46+
unsafe {
47+
let r = &mut self.0;
48+
self.1.call_once(|| {
49+
*r = transmute(Box::new(f()));
50+
});
51+
52+
&*self.0
53+
}
54+
}
55+
}
56+
57+
unsafe impl<T: Sync> Sync for Lazy<T> {}

src/lib.rs

+24-41
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ trait.
3535
3636
Using the macro:
3737
38-
```rust
38+
```ignore
3939
#[macro_use]
4040
extern crate lazy_static;
4141
@@ -71,6 +71,25 @@ The `Deref` implementation uses a hidden static variable that is guarded by a at
7171
#![cfg_attr(feature="nightly", feature(const_fn, core_intrinsics))]
7272
#![crate_type = "dylib"]
7373

74+
pub mod lazy;
75+
76+
#[cfg(feature="nightly")]
77+
#[macro_export]
78+
macro_rules! lazy_create {
79+
($T:ty) => {
80+
static LAZY: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy::new();
81+
}
82+
}
83+
84+
#[cfg(not(feature="nightly"))]
85+
#[macro_export]
86+
macro_rules! lazy_create {
87+
($T:ty) => {
88+
use std::sync::ONCE_INIT;
89+
static mut LAZY: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy(0 as *const $T, ONCE_INIT);
90+
}
91+
}
92+
7493
#[macro_export]
7594
macro_rules! lazy_static {
7695
($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
@@ -84,51 +103,15 @@ macro_rules! lazy_static {
84103
impl ::std::ops::Deref for $N {
85104
type Target = $T;
86105
fn deref<'a>(&'a self) -> &'a $T {
87-
#[inline(always)]
88-
fn __static_ref_initialize() -> $T { $e }
89-
90106
unsafe {
91-
use std::sync::{Once, ONCE_INIT};
92-
93-
#[inline(always)]
94-
fn require_sync<T: Sync>(_: &T) { }
95-
96107
#[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-
}
108+
fn __static_ref_initialize() -> $T { $e }
114109

115-
#[inline(always)]
116-
#[cfg(not(feature="nightly"))]
117110
unsafe fn __stability() -> &'static $T {
118-
use std::mem::transmute;
119-
120-
static mut DATA: *const $T = 0 as *const $T;
121-
static mut ONCE: Once = ONCE_INIT;
122-
ONCE.call_once(|| {
123-
DATA = transmute::<Box<$T>, *const $T>(
124-
Box::new(__static_ref_initialize()));
125-
});
126-
&*DATA
111+
lazy_create!($T);
112+
LAZY.get(__static_ref_initialize)
127113
}
128-
129-
let static_ref = __stability();
130-
require_sync(static_ref);
131-
static_ref
114+
__stability()
132115
}
133116
}
134117
}

0 commit comments

Comments
 (0)