Skip to content

Commit 3250eea

Browse files
committed
Moved user initialization code out of the unsafe block.
The user-provided initialization expression was being evaluated in an unsafe block, because it appeared as the argument of transmute. This meant that 1) the user code could do unsafe operations without it being marked by an unsafe block, and 2) writing an unsafe block in the user code produced a warning. Now the user code is spliced into an inline function defined above the unsafe block, and the function is called inside the unsafe block.
1 parent b8b1431 commit 3250eea

File tree

2 files changed

+9
-1
lines changed

2 files changed

+9
-1
lines changed

src/lazy_static.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,14 @@ macro_rules! lazy_static {
8989
#[inline(always)]
9090
fn require_sync<T: Sync>(_: &T) { }
9191

92+
#[inline(always)]
93+
fn initialize() -> Box<$T> { Box::new($e) }
94+
9295
unsafe {
9396
static mut __static: *const $T = 0 as *const $T;
9497
static mut __ONCE: Once = ONCE_INIT;
9598
__ONCE.call_once(|| {
96-
__static = transmute::<Box<$T>, *const $T>(Box::new(($e)));
99+
__static = transmute::<Box<$T>, *const $T>(initialize());
97100
});
98101
let static_ref = &*__static;
99102
require_sync(static_ref);

tests/test.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ lazy_static! {
1313
m.insert(2, "ghi");
1414
m
1515
};
16+
// This should not compile if the unsafe is removed.
17+
static ref UNSAFE: u32 = unsafe {
18+
std::mem::transmute::<i32, u32>(-1)
19+
};
1620
// This *should* triggger warn(dead_code) by design.
1721
static ref UNUSED: () = ();
1822
}
@@ -28,6 +32,7 @@ fn test_basic() {
2832
assert!(HASHMAP.get(&1).is_some());
2933
assert!(HASHMAP.get(&3).is_none());
3034
assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]);
35+
assert_eq!(*UNSAFE, std::u32::MAX);
3136
}
3237

3338
#[test]

0 commit comments

Comments
 (0)