rust-lang-nursery / lazy-static.rs

A small macro for defining lazy evaluated static variables in Rust.
Apache License 2.0
1.9k stars 111 forks source link

lazy_static! fails to compile when a static ref is cfg'd out #165

Open LunarLambda opened 4 years ago

LunarLambda commented 4 years ago

rustc: 1.40.0 lazy_static: 1.4.0

I am calling a thread-unsafe unix libc function. So, I have a Mutex in my code to mitigate this issue. Linux provides a thread-safe version, so it's not needed on there.

So, I have the following code:

lazy_static! {
    #[cfg(all(unix, not(target_os = "linux")))]
    static ref MY_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
}

This configuration predicate works fine on functions, types, and even normal statics, but when used inside lazy_static!, I instead get a rather unhelpful "expected type, found static MY_MUTEX" error.

sfackler commented 4 years ago

That error does not have anything to do with the attribute. The type of MY_MUTEX is not Mutex<()>, but rather a new type (named MY_MUTEX) that derefs to Mutex<()>. You may need to do e.g. &*MY_MUTEX to get a &Mutex<()>.

LunarLambda commented 4 years ago

I am confused. What type should I put there then? Besides, it compiles if I remove the attribute, or change it to be simpler (for example, #[cfg(unix)] works...)

On Thu, 2 Jan 2020, 01:02 Steven Fackler, notifications@github.com wrote:

That error does not have anything to do with the attribute. The type of MY_MUTEX is not Mutex<()>, but rather a new type (named MY_MUTEX) that derefs to Mutex<()>. You may need to do e.g. &*MY_MUTEX to get a &Mutex<()>.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/rust-lang-nursery/lazy-static.rs/issues/165?email_source=notifications&email_token=AJI55IRHEMR4WY7CEMGLEZLQ3UVHZA5CNFSM4KB5JVH2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEH5PHTI#issuecomment-570094541, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJI55IUV6T3NPTINLAS3JTLQ3UVHZANCNFSM4KB5JVHQ .

sfackler commented 4 years ago

What code specifically compiles or does not compile?

LunarLambda commented 4 years ago

The snippet shown in the issue. My code is not the problem, as I could reproduce it in a completely empty crate as well.

It gives me the error on the macro invocation itself, not on subsequent use of the Mutex.

On Thu, 2 Jan 2020, 13:21 Steven Fackler, notifications@github.com wrote:

What specifically compiles or does not compile?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/rust-lang-nursery/lazy-static.rs/issues/165?email_source=notifications&email_token=AJI55IXHUONIUUAH2DNLP7TQ3XL6LA5CNFSM4KB5JVH2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEH6HGUA#issuecomment-570192720, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJI55IWSGEA33KSWZKOECTDQ3XL6LANCNFSM4KB5JVHQ .

sfackler commented 4 years ago

Oh, sorry, I thought that error was coming from the usage site.

It doesn't appear to be due to the complexity of the cfg, just if the cfg evaluates to true or false. You can move the cfg to the macro call itself as a workaround:

#[cfg(all(unix, not(target_os = "linux")))]
lazy_static! {
    static ref MY_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
}
LunarLambda commented 4 years ago

Ah. I was slightly mislead by the documentation saying doc comments and attributes are supported, but the only example showed doc comments being placed on the static item, not the macro invocation.

Thank you!

On Thu, 2 Jan 2020, 13:32 Steven Fackler, notifications@github.com wrote:

Oh, sorry, I thought that error was coming from the usage site.

It doesn't appear to be due to the complexity of the cfg, just if the cfg evaluates to true or false. You can move the cfg to the macro call itself as a workaround:

[cfg(all(unix, not(target_os = "linux")))]lazy_static! {

static ref MY_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());

}

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/rust-lang-nursery/lazy-static.rs/issues/165?email_source=notifications&email_token=AJI55ISTJRA62PR5HO6DZLDQ3XNHHA5CNFSM4KB5JVH2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEH6HXVY#issuecomment-570194903, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJI55IWBV6UHFY76SKQNXNLQ3XNHHANCNFSM4KB5JVHQ .

KodrAus commented 4 years ago

Since lazy_static evaluates to multiple items, and not all of those items accept all attributes, we'd potentially break callers if we fixed this by duplicating the attributes on the impl blocks. If we could replace the macro internals with something like https://github.com/rust-lang/rfcs/pull/2788 so that the macro expanded to a single item then it might be possible, but that would probably also break uses.