digitalmars.D.learn - more cyclical confoundedness
- Ellery Newcomer (37/37) Apr 05 2009 Hello.
- Ellery Newcomer (8/61) Apr 08 2009 Och, I feel so alone. I'll rephrase the question:
- Jarrett Billingsley (20/27) Apr 08 2009 Cyclic module initialization dependencies are not detected by the
Hello. When I have three files test1.d test2.d test3.d as follows: module test1; import tango.io.Stdout; import test3; static this(){ Stdout("test1\n"); } module test2; import test1; //no ctor module test3; import tango.io.Stdout; import test2; static this(){ Stdout("test3\n"); } and main.d: module main; import tango.io.Stdout; import test1; import test2; import test3; main(){} static this(){ Stdout("main\n"); } It works dandy, compiling AND running to give me test3 test1 main But if I change the import order to begin with import test3; it barfs with the cyclic dependency runtime error. All other combinations give output same as the first. Now, what the heck is going on? As near as I can tell these should all fail at runtime. Or am I missing something?
Apr 05 2009
Och, I feel so alone. I'll rephrase the question: How is a cyclic dependency defined? Is it a cycle formed by imports in which two or more of the modules contain static constructors? The reason I ask is because I'm trying to mechanize finding these cyclic dependencies, and my example suggests that the above assumption will generate a large proportion of false positives, or else the compiler ignores a large proportion of true positives. Ellery Newcomer wrote:Hello. When I have three files test1.d test2.d test3.d as follows: module test1; import tango.io.Stdout; import test3; static this(){ Stdout("test1\n"); } module test2; import test1; //no ctor module test3; import tango.io.Stdout; import test2; static this(){ Stdout("test3\n"); } and main.d: module main; import tango.io.Stdout; import test1; import test2; import test3; main(){} static this(){ Stdout("main\n"); } It works dandy, compiling AND running to give me test3 test1 main But if I change the import order to begin with import test3; it barfs with the cyclic dependency runtime error. All other combinations give output same as the first. Now, what the heck is going on? As near as I can tell these should all fail at runtime. Or am I missing something?
Apr 08 2009
On Wed, Apr 8, 2009 at 11:14 PM, Ellery Newcomer <ellery-newcomer utulsa.edu> wrote:Och, I feel so alone. I'll rephrase the question: How is a cyclic dependency defined? Is it a cycle formed by imports in which two or more of the modules contain static constructors? The reason I ask is because I'm trying to mechanize finding these cyclic dependencies, and my example suggests that the above assumption will generate a large proportion of false positives, or else the compiler ignores a large proportion of true positives.Cyclic module initialization dependencies are not detected by the compiler, but instead by the runtime. The reasons for this are somewhat weak (you _might_ have a separately-compiled module whose interface is defined in a .di file that doesn't tell you there's a static ctor.. sounds like a deficiency in .di files to me). Basically the way it works is that it starts with the module that contains main (I think?), then does a depth-first inorder initialization of all modules that it imports. When a module with a static ctor is encountered, it is flagged as "in the process of being initialized", then any modules that it imports are initialized, then its static ctor is run, and then it is flagged as "done being initialized". If a module has no static ctor, it is never marked as "in the process". If, at any time, an attempt is made to initialize a module which is already in the process, an exception is thrown and you get the dreadful "cyclic dependency" runtime error. Your example code confounds me. I don't know why it behaves differently based on import order. Like you, I'd expect for there to be a cyclic initialization in either case.
Apr 08 2009