diff --git a/src/lib.rs b/src/lib.rs index 51d66ef..f4eb0d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,24 +116,12 @@ pub use core::ops::Deref as __Deref; #[cfg_attr(feature="nightly", allow_internal_unstable)] #[doc(hidden)] macro_rules! __lazy_static_internal { - ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*); - }; - ($(#[$attr:meta])* pub(in $pub_in:path) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@PUB_IN, $pub_in, $(#[$attr])* static ref $N : $T = $e; $($t)*); - }; - ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*); - }; - (@PUB_IN, $pub_in:path, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@MAKE TY, PUB_IN, $pub_in, $(#[$attr])*, $N); + // optional visibility restrictions are wrapped in `()` to allow for + // explicitly passing otherwise implicit information about private items + ($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { + __lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N); __lazy_static_internal!(@TAIL, $N : $T = $e); - __lazy_static_internal!($($t)*); - }; - (@$VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@MAKE TY, $VIS, $(#[$attr])*, $N); - __lazy_static_internal!(@TAIL, $N : $T = $e); - __lazy_static_internal!($($t)*); + lazy_static!($($t)*); }; (@TAIL, $N:ident : $T:ty = $e:expr) => { impl $crate::__Deref for $N { @@ -159,32 +147,15 @@ macro_rules! __lazy_static_internal { } } }; - (@MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => { + // `vis` is wrapped in `()` to prevent parsing ambiguity + (@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => { #[allow(missing_copy_implementations)] #[allow(non_camel_case_types)] #[allow(dead_code)] $(#[$attr])* - pub struct $N {__private_field: ()} + $($vis)* struct $N {__private_field: ()} #[doc(hidden)] - pub static $N: $N = $N {__private_field: ()}; - }; - (@MAKE TY, PUB_IN, $pub_in:path, $(#[$attr:meta])*, $N:ident) => { - #[allow(missing_copy_implementations)] - #[allow(non_camel_case_types)] - #[allow(dead_code)] - $(#[$attr])* - pub(in $pub_in) struct $N {__private_field: ()} - #[doc(hidden)] - pub(in $pub_in) static $N: $N = $N {__private_field: ()}; - }; - (@MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => { - #[allow(missing_copy_implementations)] - #[allow(non_camel_case_types)] - #[allow(dead_code)] - $(#[$attr])* - struct $N {__private_field: ()} - #[doc(hidden)] - static $N: $N = $N {__private_field: ()}; + $($vis)* static $N: $N = $N {__private_field: ()}; }; () => () } @@ -193,13 +164,14 @@ macro_rules! __lazy_static_internal { #[cfg_attr(feature="nightly", allow_internal_unstable)] macro_rules! lazy_static { ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*); - }; - ($(#[$attr:meta])* pub (in $pub_in:path) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@PUB_IN, $pub_in, $(#[$attr])* static ref $N : $T = $e; $($t)*); + // use `()` to explicitly forward the information about private items + __lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*); }; ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - __lazy_static_internal!(@PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*); + __lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*); + }; + ($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { + __lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*); }; () => () } diff --git a/tests/compile-fail/incorrect_visibility_restriction.rs b/tests/compile-fail/incorrect_visibility_restriction.rs new file mode 100644 index 0000000..e2e5238 --- /dev/null +++ b/tests/compile-fail/incorrect_visibility_restriction.rs @@ -0,0 +1,10 @@ +// incorrect visibility restriction +#[macro_use] +extern crate lazy_static; + +lazy_static! { + pub(nonsense) static ref WRONG: () = (); + //~^ ERROR incorrect visibility restriction +} + +fn main() { } diff --git a/tests/compile-fail/static_is_private.rs b/tests/compile-fail/static_is_private.rs new file mode 100644 index 0000000..a88c1c6 --- /dev/null +++ b/tests/compile-fail/static_is_private.rs @@ -0,0 +1,14 @@ +#[macro_use] +extern crate lazy_static; + +mod outer { + pub mod inner { + lazy_static! { + pub(in outer) static ref FOO: () = (); + } + } +} + +fn main() { + assert_eq!(*outer::inner::FOO, ()); //~ ERROR static `FOO` is private +} diff --git a/tests/test.rs b/tests/test.rs index bece9d6..fbf225d 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -80,16 +80,26 @@ mod visibility { static ref BAR: Box = Box::new(98); } + pub mod inner { + lazy_static! { + pub(in visibility) static ref BAZ: Box = Box::new(42); + pub(crate) static ref BAG: Box = Box::new(37); + } + } + #[test] fn sub_test() { assert_eq!(**FOO, 0); assert_eq!(**BAR, 98); + assert_eq!(**inner::BAZ, 42); + assert_eq!(**inner::BAG, 37); } } #[test] fn test_visibility() { assert_eq!(*visibility::FOO, Box::new(0)); + assert_eq!(*visibility::inner::BAG, Box::new(37)); } // This should not cause a warning about a missing Copy implementation