www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Argh!! Cyclic dependencies!!!

reply "Nick Sabalausky" <a a.a> writes:
These module constructor "Cyclic dependencies" errors are really starting to 
piss me off. I feel like I'm back in the days when you'd sneeze and DMD 
would vomit out 100 forward reference errors just because you didn't write 
your whole damn app in one giant ultra-module. (/me takes a breather to 
chill out...Ok...)

I don't suppose there's any chance we could get a quick little:

import foo;

pragma(staticCtorsAvoid, foo);
// Or
pragma(staticCtorsRunBefore, foo);
// Or
pragma(staticCtorsRunAfter, foo);

static this()
{
    // do trivial shit that doesn't touch foo
}

Could we? I don't care which it is. I don't care if it doesn't enforce any 
safety at all. I don't care if it gets depricated in favor of an alternate 
solution in a later version. I just need a way to say "this'll work, dmd, 
just do it and quit yer damn whinin'!!" Doesn't need to be perfect, just 
needs to work. At the very least, if I manage to be able to hack something 
like that it in, would there be any chance of it getting accepted?
Mar 18 2011
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Nick Sabalausky Wrote:

 These module constructor "Cyclic dependencies" errors are really starting to 
 piss me off. I feel like I'm back in the days when you'd sneeze and DMD 
 would vomit out 100 forward reference errors just because you didn't write 
 your whole damn app in one giant ultra-module. (/me takes a breather to 
 chill out...Ok...)
 
 I don't suppose there's any chance we could get a quick little:
 
 import foo;
 
 pragma(staticCtorsAvoid, foo);
 // Or
 pragma(staticCtorsRunBefore, foo);
 // Or
 pragma(staticCtorsRunAfter, foo);
 
 static this()
 {
     // do trivial shit that doesn't touch foo
 }
 

Could module-level globals be treated like local variables to the static constructor for the purpose of checking purity? AKA static this() pure { // trivial stuff // calls weakly pure functions // writes module-level globals // reads module-level globals // etc... } That's compiler enforceable and effectively means that stati constructor does not count as part of a cyclic dependency...
Mar 18 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-03-18 19:24:41 -0400, Jason House <jason.james.house gmail.com> said:

 Nick Sabalausky Wrote:
 
 These module constructor "Cyclic dependencies" errors are really starting to
 piss me off. I feel like I'm back in the days when you'd sneeze and DMD
 would vomit out 100 forward reference errors just because you didn't write
 your whole damn app in one giant ultra-module. (/me takes a breather to
 chill out...Ok...)
 
 I don't suppose there's any chance we could get a quick little:
 
 import foo;
 
 pragma(staticCtorsAvoid, foo);
 // Or
 pragma(staticCtorsRunBefore, foo);
 // Or
 pragma(staticCtorsRunAfter, foo);
 
 static this()
 {
 // do trivial shit that doesn't touch foo
 }
 

Could module-level globals be treated like local variables to the static constructor for the purpose of checking purity? AKA static this() pure { // trivial stuff // calls weakly pure functions // writes module-level globals // reads module-level globals // etc... } That's compiler enforceable and effectively means that stati constructor does not count as part of a cyclic dependency...

That would work nicely, except for one thing: static constructors can be used to build immutable global variables. And pure functions have access to immutable global variables. This means two things: 1. purity isn't really guarantied for pure functions inside a module constructor 2. pure functions could access immutable global variables of other modules before their initialization I think the pragma is a more viable solution, athough not very elegant. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Mar 18 2011
parent "Nick Sabalausky" <a a.a> writes:
"Michel Fortin" <michel.fortin michelf.com> wrote in message 
news:im0s22$2fap$1 digitalmars.com...
 On 2011-03-18 19:24:41 -0400, Jason House <jason.james.house gmail.com> 
 said:

 Nick Sabalausky Wrote:

 These module constructor "Cyclic dependencies" errors are really 
 starting to
 piss me off. I feel like I'm back in the days when you'd sneeze and DMD
 would vomit out 100 forward reference errors just because you didn't 
 write
 your whole damn app in one giant ultra-module. (/me takes a breather to
 chill out...Ok...)

 I don't suppose there's any chance we could get a quick little:

 import foo;

 pragma(staticCtorsAvoid, foo);
 // Or
 pragma(staticCtorsRunBefore, foo);
 // Or
 pragma(staticCtorsRunAfter, foo);

 static this()
 {
 // do trivial shit that doesn't touch foo
 }

Could module-level globals be treated like local variables to the static constructor for the purpose of checking purity? AKA static this() pure { // trivial stuff // calls weakly pure functions // writes module-level globals // reads module-level globals // etc... } That's compiler enforceable and effectively means that stati constructor does not count as part of a cyclic dependency...

That would work nicely, except for one thing: static constructors can be used to build immutable global variables. And pure functions have access to immutable global variables. This means two things: 1. purity isn't really guarantied for pure functions inside a module constructor 2. pure functions could access immutable global variables of other modules before their initialization I think the pragma is a more viable solution, athough not very elegant.

Yea, I agree the pragma is inelegant, but I figure a quick-n-dirty stop-gap workaround for this is a lot better than waiting for a proper solution.
Mar 18 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 18 Mar 2011 17:42:58 -0400, Nick Sabalausky <a a.a> wrote:

 These module constructor "Cyclic dependencies" errors are really  
 starting to
 piss me off. I feel like I'm back in the days when you'd sneeze and DMD
 would vomit out 100 forward reference errors just because you didn't  
 write
 your whole damn app in one giant ultra-module. (/me takes a breather to
 chill out...Ok...)

 I don't suppose there's any chance we could get a quick little:

 import foo;

 pragma(staticCtorsAvoid, foo);
 // Or
 pragma(staticCtorsRunBefore, foo);
 // Or
 pragma(staticCtorsRunAfter, foo);

 static this()
 {
     // do trivial shit that doesn't touch foo
 }

 Could we? I don't care which it is. I don't care if it doesn't enforce  
 any
 safety at all. I don't care if it gets depricated in favor of an  
 alternate
 solution in a later version. I just need a way to say "this'll work, dmd,
 just do it and quit yer damn whinin'!!" Doesn't need to be perfect, just
 needs to work. At the very least, if I manage to be able to hack  
 something
 like that it in, would there be any chance of it getting accepted?

If you are interested, the code that runs the static ctors is in druntime, not the compiler. So you can turn off the errors if you want in your local copy of druntime. FWIW, there is a "standalone" flag which allows you to skip cycle detection on that module. I'm not quite sure why the compiler sets that flag, but it has something to do with little modules created by the compiler itself. When I rewrote the cycle detection code, I used to have an idea of why, but it's faded from my memory. In any case, I think you could do something repulsive like naming your module nodeps_x instead of x, and have the cycle detection skip over that module when detecting cycles. Bottom line is, there is no valid static data before static ctors run, so you must figure out how to get the info to the cycle detection routine without static data. If we are changing the compiler, I'd like this: standalone module foo; which would tell the compiler to set the standalone flag, no proof required. I don't think it's really possible to verify that a static ctor does not depend on outside data without full analysis which isn't currently possible. -Steve
Mar 21 2011
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:op.vso2wwsweav7ka steve-laptop...
 If you are interested, the code that runs the static ctors is in druntime, 
 not the compiler.

Yea, I had a feeling druntime would be involved since the cycles get reported at runtime. Thanks for confirming, though.
 In any case, I think you could do something repulsive like naming your 
 module nodeps_x instead of x, and have the cycle detection skip over that 
 module when detecting cycles.  Bottom line is, there is no valid static 
 data before static ctors run, so you must figure out how to get the info 
 to the cycle detection routine without static data.

I'm not very familiar with how druntime works. Are you implying that sending information from a pragma to druntime would inherently require using valid static data from a static ctor? I take it that the answer from the-powers-that-be to the question "Is there a chance that a stop-gap solution might be accepted?" is "no comment"? If there's any worry about a "there's a chance of it" being misinterpreted as a promise for inclusion, I can assure that I'm an adult and do know the difference between "yes" and "maybe".
Mar 21 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 21 Mar 2011 18:45:23 -0400, Nick Sabalausky <a a.a> wrote:

 "Steven Schveighoffer" <schveiguy yahoo.com> wrote in message
 news:op.vso2wwsweav7ka steve-laptop...
 If you are interested, the code that runs the static ctors is in  
 druntime,
 not the compiler.

Yea, I had a feeling druntime would be involved since the cycles get reported at runtime. Thanks for confirming, though.
 In any case, I think you could do something repulsive like naming your
 module nodeps_x instead of x, and have the cycle detection skip over  
 that
 module when detecting cycles.  Bottom line is, there is no valid static
 data before static ctors run, so you must figure out how to get the info
 to the cycle detection routine without static data.

I'm not very familiar with how druntime works. Are you implying that sending information from a pragma to druntime would inherently require using valid static data from a static ctor?

No, I was saying if you want a stop-gap solution that does not involve modifying the compiler, you have to use what the compiler gives you. Namely, what is in the ModuleInfo. You can't rely on something like a static initializer. If you have a pragma, no changes to druntime are necessary, it already has the capability of skipping modules marked with the standalone flag.
 I take it that the answer from the-powers-that-be to the question "Is  
 there
 a chance that a stop-gap solution might be accepted?" is "no comment"? If
 there's any worry about a "there's a chance of it" being misinterpreted  
 as a
 promise for inclusion, I can assure that I'm an adult and do know the
 difference between "yes" and "maybe".

I think a pragma or an annotation would be considered by the powers-that-be. No response from Walter is usually a good sign that he's not adamantly against it ;) -Steve
Mar 22 2011