1  #[macro_use]
2  extern crate lazy_static;
3  use std::collections::HashMap;
4  
5  lazy_static! {
6      /// Documentation!
7      pub static ref NUMBER: u32 = times_two(3);
8  
9      static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)];
10  
11      /// More documentation!
12      #[allow(unused_variables)]
13      #[derive(Copy, Clone, Debug)]
14      pub static ref STRING: String = "hello".to_string();
15  
16      static ref HASHMAP: HashMap<u32, &'static str> = {
17          let mut m = HashMap::new();
18          m.insert(0, "abc");
19          m.insert(1, "def");
20          m.insert(2, "ghi");
21          m
22      };
23  
24      // This should not compile if the unsafe is removed.
25      static ref UNSAFE: u32 = unsafe {
26          std::mem::transmute::<i32, u32>(-1)
27      };
28  }
29  
30  lazy_static! {
31      static ref S1: &'static str = "a";
32      static ref S2: &'static str = "b";
33  }
34  lazy_static! {
35      static ref S3: String = [*S1, *S2].join("");
36  }
37  
38  #[test]
s3()39  fn s3() {
40      assert_eq!(&*S3, "ab");
41  }
42  
times_two(n: u32) -> u3243  fn times_two(n: u32) -> u32 {
44      n * 2
45  }
46  
47  #[test]
test_basic()48  fn test_basic() {
49      assert_eq!(&**STRING, "hello");
50      assert_eq!(*NUMBER, 6);
51      assert!(HASHMAP.get(&1).is_some());
52      assert!(HASHMAP.get(&3).is_none());
53      assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]);
54      assert_eq!(*UNSAFE, std::u32::MAX);
55  }
56  
57  #[test]
test_repeat()58  fn test_repeat() {
59      assert_eq!(*NUMBER, 6);
60      assert_eq!(*NUMBER, 6);
61      assert_eq!(*NUMBER, 6);
62  }
63  
64  #[test]
test_meta()65  fn test_meta() {
66      // this would not compile if STRING were not marked #[derive(Copy, Clone)]
67      let copy_of_string = STRING;
68      // just to make sure it was copied
69      assert!(&STRING as *const _ != &copy_of_string as *const _);
70  
71      // this would not compile if STRING were not marked #[derive(Debug)]
72      assert_eq!(format!("{:?}", STRING), "STRING { __private_field: () }".to_string());
73  }
74  
75  mod visibility {
76      lazy_static! {
77          pub static ref FOO: Box<u32> = Box::new(0);
78          static ref BAR: Box<u32> = Box::new(98);
79      }
80  
81      pub mod inner {
82          lazy_static! {
83              pub(in visibility) static ref BAZ: Box<u32> = Box::new(42);
84              pub(crate) static ref BAG: Box<u32> = Box::new(37);
85          }
86      }
87  
88      #[test]
sub_test()89      fn sub_test() {
90          assert_eq!(**FOO, 0);
91          assert_eq!(**BAR, 98);
92          assert_eq!(**inner::BAZ, 42);
93          assert_eq!(**inner::BAG, 37);
94      }
95  }
96  
97  #[test]
test_visibility()98  fn test_visibility() {
99      assert_eq!(*visibility::FOO, Box::new(0));
100      assert_eq!(*visibility::inner::BAG, Box::new(37));
101  }
102  
103  // This should not cause a warning about a missing Copy implementation
104  lazy_static! {
105      pub static ref VAR: i32 = { 0 };
106  }
107  
108  #[derive(Copy, Clone, Debug, PartialEq)]
109  struct X;
110  struct Once(X);
111  const ONCE_INIT: Once = Once(X);
112  static DATA: X = X;
113  static ONCE: X = X;
require_sync() -> X114  fn require_sync() -> X { X }
transmute() -> X115  fn transmute() -> X { X }
__static_ref_initialize() -> X116  fn __static_ref_initialize() -> X { X }
test(_: Vec<X>) -> X117  fn test(_: Vec<X>) -> X { X }
118  
119  // All these names should not be shadowed
120  lazy_static! {
121      static ref ITEM_NAME_TEST: X = {
122          test(vec![X, Once(X).0, ONCE_INIT.0, DATA, ONCE,
123                    require_sync(), transmute(),
124                    // Except this, which will sadly be shadowed by internals:
125                    // __static_ref_initialize()
126                    ])
127      };
128  }
129  
130  #[test]
item_name_shadowing()131  fn item_name_shadowing() {
132      assert_eq!(*ITEM_NAME_TEST, X);
133  }
134  
135  use std::sync::atomic::AtomicBool;
136  #[allow(deprecated)]
137  use std::sync::atomic::ATOMIC_BOOL_INIT;
138  use std::sync::atomic::Ordering::SeqCst;
139  
140  #[allow(deprecated)]
141  static PRE_INIT_FLAG: AtomicBool = ATOMIC_BOOL_INIT;
142  
143  lazy_static! {
144      static ref PRE_INIT: () = {
145          PRE_INIT_FLAG.store(true, SeqCst);
146          ()
147      };
148  }
149  
150  #[test]
pre_init()151  fn pre_init() {
152      assert_eq!(PRE_INIT_FLAG.load(SeqCst), false);
153      lazy_static::initialize(&PRE_INIT);
154      assert_eq!(PRE_INIT_FLAG.load(SeqCst), true);
155  }
156  
157  lazy_static! {
158      static ref LIFETIME_NAME: for<'a> fn(&'a u8) = { fn f(_: &u8) {} f };
159  }
160  
161  #[test]
lifetime_name()162  fn lifetime_name() {
163      let _ = LIFETIME_NAME;
164  }
165