Open luser opened 6 years ago
Yeah, that's a unfortunate error scenario - I'm not sure if we can do anything about it.
Maybe an extra boolean flag for a recursion check during initialization, but even for debug mode I'm not sure if thats to heavy-handed.
Is this sound? Is Once
reentrance-safe and blocking in this case, guaranteeing a deadlock?
EDIT: looks like it! https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once
Hello, I think I ran into the same problem with this example:
lazy_static::lazy_static! {
static ref FOO: [usize; 2] = [0, FOO[0]];
}
fn main() {
println!("{}", FOO[0]);
}
The code compiles fine but hangs.
The macro could shadow the name with another definition, but I can't think of any way to cause a compiler error only on use. At most it could do something like this:
struct RecursiveUseWithinInitialierOfFOO;
const FOO: RecursiveUseWithinInitialierOfFOO = RecursiveUseWithinInitialierOfFOO;
And then the type errors might be a decent enough hint.
However, there's not really any way I can think of to stop code outside of the initializer expression, from using it, and getting called from the initializer, other than some kind of attribute that makes the compiler warn if the <typeof(FOO) as Deref>::deref
method can ever call itself (that looks through the entire callgraph involving Once::call_once
and whatnot - a bit like the "unconditional recursion" lint, but more powerful).
I refactored some code I had that was creating a
HashSet
from a const slice to uselazy_static
instead. I renamed theconst
and used its original name for thestatic
, and then copy/pasted the initialization and forgot to rename the variable it was using, so thestatic
wound up trying to initialize by iterating over itself. Surprisingly (to me), the code compiled anyway!Here's a simple reduced testcase: https://play.rust-lang.org/?gist=d77058ab6da1a4e7815fab94305f2092&version=stable
Running this will deadlock and time out on the Playground.
I realize that this is probably hard to fix within the constraints of what Rust macros can do, but it's pretty unfortunate!