View mode: basic / threaded / horizontal-split · Log in · Help
July 14, 2005
Could static ctors / module init be a little more intelligent?
Say I have two modules named A and B.

Each module needs to know of a class from the other module.

Each module also needs a static ctor.

Neither static ctor refers to the other module, only to stuff in the current 
module.

However, when run, I get the error "Error: circular initialization 
dependency with module A."

This is the result of some rather simplistic dependence determination on the 
part of the compiler.  Both have static ctors, and both import each other, 
therefore, it _must_ be a circular dependency.

But look at this:

[A.d]
module a;

private import b;

int x;

static this()
{
x=5;
}

void fork()
{
   x=y;
}

[B.d]
module b;

private import b;

int y;

static this()
{
y=10;
}

void knife()
{
   y=x;
}

As you can see, neither module requires for the other module to be 
initialized when it is.  But I get the error at runtime, nonetheless.

This is irritating.  Could the check for "depended-upon module 
initialization" be done when a member is accessed in the static ctor() 
rather than unconditionally?
July 14, 2005
Re: Could static ctors / module init be a little more intelligent?
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message 
news:db6867$4oa$1@digitaldaemon.com...
> Say I have two modules named A and B.
>
> Each module needs to know of a class from the other module.
>
> Each module also needs a static ctor.
>
> Neither static ctor refers to the other module, only to stuff in the 
> current module.
>
> However, when run, I get the error "Error: circular initialization 
> dependency with module A."
>
> This is the result of some rather simplistic dependence determination on 
> the part of the compiler.  Both have static ctors, and both import each 
> other, therefore, it _must_ be a circular dependency.
[snip]
> This is irritating.  Could the check for "depended-upon module 
> initialization" be done when a member is accessed in the static ctor() 
> rather than unconditionally?

What about when the static ctor calls something that accesses the other 
module?
I think the current rule is the most reasonable since trying to figure out 
the run-time dependencies is impossible in general.
July 14, 2005
Re: Could static ctors / module init be a little more intelligent?
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message 
news:db6k70$fd1$1@digitaldaemon.com...
>> This is irritating.  Could the check for "depended-upon module 
>> initialization" be done when a member is accessed in the static ctor() 
>> rather than unconditionally?
>
> What about when the static ctor calls something that accesses the other 
> module?

But that's what I said - the check to see if the other module is initialized 
should be done before a member of it is accessed in the module ctor, instead 
of before the module ctor is run.

> I think the current rule is the most reasonable since trying to figure out 
> the run-time dependencies is impossible in general.

That's not entirely true.  At least for the static ctors, it would be 
possible to see if any members of an imported module are used.  In the 
semantic pass, see if anything resolves to a symbol declared in the imported 
module - if so, that module depends upon the imported module to be 
initialized before.  This way, the compiler would be able to determine the 
dependence graphs, and true circular dependencies could be reported at 
compile-time.
July 14, 2005
Re: Could static ctors / module init be a little more intelligent?
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message 
news:db6m5e$gi6$1@digitaldaemon.com...
> "Ben Hinkle" <bhinkle@mathworks.com> wrote in message 
> news:db6k70$fd1$1@digitaldaemon.com...
>>> This is irritating.  Could the check for "depended-upon module 
>>> initialization" be done when a member is accessed in the static ctor() 
>>> rather than unconditionally?
>>
>> What about when the static ctor calls something that accesses the other 
>> module?
>
> But that's what I said - the check to see if the other module is 
> initialized should be done before a member of it is accessed in the module 
> ctor, instead of before the module ctor is run.

Maybe I don't understand. What I meant was:
 module a;
 import b;
 static this() { foo(); }
 void foo(){bar();}

 module b;
 import a;
 statis this(){bar();}
 void bar(){printf("who wins?\n");}

In order for dmd to know that a's ctor depends on b but b's ctor doesn't it 
has to track the run-time behavior. Imagine now that the logic before 
calling bar is arbitrarily complex. Imagine if foo was
 void foo(){ if (hell is frozen) bar(); }

>> I think the current rule is the most reasonable since trying to figure 
>> out the run-time dependencies is impossible in general.
>
> That's not entirely true.  At least for the static ctors, it would be 
> possible to see if any members of an imported module are used.  In the 
> semantic pass, see if anything resolves to a symbol declared in the 
> imported module - if so, that module depends upon the imported module to 
> be initialized before.  This way, the compiler would be able to determine 
> the dependence graphs, and true circular dependencies could be reported at 
> compile-time.

It just seems like a slippeery slope to me.
July 15, 2005
Re: Could static ctors / module init be a little more intelligent?
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message 
news:db6q3a$jfk$1@digitaldaemon.com...
> Maybe I don't understand. What I meant was:
>  module a;
>  import b;
>  static this() { foo(); }
>  void foo(){bar();}
>
>  module b;
>  import a;
>  statis this(){bar();}
>  void bar(){printf("who wins?\n");}
>
> In order for dmd to know that a's ctor depends on b but b's ctor doesn't 
> it has to track the run-time behavior. Imagine now that the logic before 
> calling bar is arbitrarily complex. Imagine if foo was
>  void foo(){ if (hell is frozen) bar(); }

I didn't think about having code like you posted.  Now this fits right in 
with determining whether to issue an error for "function does not return a 
value" or not.

I'm sorry for cluttering up the board with so many half-thought-out 
suggestions..
July 15, 2005
Re: Could static ctors / module init be a little more intelligent?
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message 
news:db6um6$mn0$1@digitaldaemon.com...
> "Ben Hinkle" <ben.hinkle@gmail.com> wrote in message 
> news:db6q3a$jfk$1@digitaldaemon.com...
>> Maybe I don't understand. What I meant was:
>>  module a;
>>  import b;
>>  static this() { foo(); }
>>  void foo(){bar();}
>>
>>  module b;
>>  import a;
>>  statis this(){bar();}
>>  void bar(){printf("who wins?\n");}
>>
>> In order for dmd to know that a's ctor depends on b but b's ctor doesn't 
>> it has to track the run-time behavior. Imagine now that the logic before 
>> calling bar is arbitrarily complex. Imagine if foo was
>>  void foo(){ if (hell is frozen) bar(); }
>
> I didn't think about having code like you posted.  Now this fits right in 
> with determining whether to issue an error for "function does not return a 
> value" or not.
>
> I'm sorry for cluttering up the board with so many half-thought-out 
> suggestions..

Don't be sorry! I remember fairly recent long threads about exactly what you 
are talking about: circular module dependencies and the semantics of module 
ctors. I think it will come up again, too. Over time I wouldn't be surprised 
if there evolves a way to tell the compiler that a's ctor depends on b but 
b's doesn't depend on a. What that syntax would look like is anyone guess.
July 15, 2005
Re: Could static ctors / module init be a little more intelligent?
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message
news:db70l8$o5d$1@digitaldaemon.com...
> Don't be sorry! I remember fairly recent long threads about exactly what
you
> are talking about: circular module dependencies and the semantics of
module
> ctors. I think it will come up again, too. Over time I wouldn't be
surprised
> if there evolves a way to tell the compiler that a's ctor depends on b but
> b's doesn't depend on a. What that syntax would look like is anyone guess.

Sometimes I think a simple rule that is easilly explained and understood is
better than a complex rule with many border cases, even if the latter does
handle a few more cases.
July 15, 2005
Re: Could static ctors / module init be a little more intelligent?
> Sometimes I think a simple rule that is easilly explained and understood  
> is
> better than a complex rule with many border cases, even if the latter  
> does handle a few more cases.

Yes, that's it. We should really avoid cluttering the language with  
"small, simple" fixes to support every feature one could possibly imagine.  
Most of the time, module initializers are not needed anyways (as with  
constructors), and for the other cases one could either redesign the  
module dependencies, or simply initialize the second module from the first:

module initialize.me;
private import initialize.myself;
package MyStruc* myStruc;


module initialize.myself;
private import initialize.me;
package MyStruc* myOtherStruc;

static this()
{
  myOtherStruc = new MyStruc;
  initialize.me.myStruc = new MyStruc;
}

Or something similar...

Ciao
uwe
Top | Discussion index | About this forum | D home