View mode: basic / threaded / horizontal-split · Log in · Help
November 29, 2012
Fixing cyclic import static construction problems
For discussion:

Cyclical Imports

Problem:

---- a.d ----
    module a;
    import b;
    static this () { ... }
---- b.d ----
    module b;
    import a;
    static this() { ... }
-------------

Static constructors for a module are only run after static constructors
for all its imports are run. Circular imports, such as the above, are
detected at run time and the program is aborted.

This can in general be solved by moving the static constructor(s) into
a third module, c.d, which does not import a or b. But, people find this
to be unnatural.

Proposed Solution:

Add a pragma,

    pragma(cyclic_imports);

This can appear anywhere in a module, and applies globally to that module.
It means that static constructors from imports that are not part of the 
cycle
are run first, and that the static constructor for this module may be 
run before
the static constructors of other modules that are part of the cycle.

If any static constructors in such a module with the pragma have
the @safe attribute, that is a compile time error.
November 29, 2012
Re: Fixing cyclic import static construction problems
On 11/28/12 9:34 PM, Walter Bright wrote:
> For discussion:
[snip]

I'd say we better finish const, immutable, and shared first.

Andrei
November 29, 2012
Re: Fixing cyclic import static construction problems
On Thursday, 29 November 2012 at 03:19:55 UTC, Andrei 
Alexandrescu wrote:
> I'd say we better finish const, immutable, and shared first.

If we put off every easy fix until all the hard fixes are done, 
it means we have longer wait times on everything....
November 29, 2012
Re: Fixing cyclic import static construction problems
Andrei Alexandrescu:

> I'd say we better finish const, immutable, and shared first.

There are few things left to implement for purity (they are 
listed in Bugzilla), but what's left to do for const and 
immutable?

Bye,
bearophile
November 29, 2012
Re: Fixing cyclic import static construction problems
> what's left to do for const and immutable?

I guess the answer is too much long, so please ignore the 
question.

Bye,
bearophile
November 29, 2012
Re: Fixing cyclic import static construction problems
On Wednesday, November 28, 2012 22:19:54 Andrei Alexandrescu wrote:
> On 11/28/12 9:34 PM, Walter Bright wrote:
> > For discussion:
> [snip]
> 
> I'd say we better finish const, immutable, and shared first.

Both problems need to be addressed, and this one is probably easier. It also 
has a huge impact on std.benchmark, so I would have thought that you'd be more 
in favor of it.

However, we do have a tendancy to bring up problems like this, discuss them 
for a while, and then let them be more or less forgotten for a while. It keeps 
happening with stuff like const ref / auto ref, shared, const and Object, const 
postblit constructors, @trusted blocks, etc. And we need to actually get them 
sorted out.

- Jonathan M Davis
November 29, 2012
Re: Fixing cyclic import static construction problems
On 11/29/12 03:34, Walter Bright wrote:
> Proposed Solution:
> 
> Add a pragma,
> 
>     pragma(cyclic_imports);
> 
> This can appear anywhere in a module, and applies globally to that module.
> It means that static constructors from imports that are not part of the cycle
> are run first, and that the static constructor for this module may be run before
> the static constructors of other modules that are part of the cycle.

Bad name. Something like "module_ctors_unordered" would be better (I don't
like that one either, but this way it's at least clear what it does).

The equivalent attribute version could be

  module mymodule @unordered_ctors;

which is better, but still has the problem that adding another module ctor
can result is silent breakage. These things can be mixed in, so something
as innocent looking as

  import some_lib;
  [...]
  mixin blah;

can already be a bug. Hence:

  static this() @unordered { /*whatever*/ }

and then either enforce that all mod-ctors have this attribute (otherwise
every ctor in that moduile gets treated as ordered), or split them into
two sets (better, but larger change; backward compatible, just requires
a new enough runtime to be used). 

Of course it could be also done as

   static this() pragma(unordered) { /*whatever*/ }

but this wouldn't really be better, and would require language change (the
fact that you cannot attach a pragma to /anything/ is already a problem,
eg for gcc-specific attributes).

"@unordered" could even be inferred, but I'm not sure how often that would
help in practice. At least w/o making module-level imports invisible inside
module ctors (which would make the deps explicit).

artur
November 29, 2012
Re: Fixing cyclic import static construction problems
On Thursday, November 29, 2012 07:36:41 Artur Skawina wrote:
> On 11/29/12 03:34, Walter Bright wrote:
> > Proposed Solution:
> > 
> > Add a pragma,
> > 
> >     pragma(cyclic_imports);
> > 
> > This can appear anywhere in a module, and applies globally to that module.
> > It means that static constructors from imports that are not part of the
> > cycle are run first, and that the static constructor for this module may
> > be run before the static constructors of other modules that are part of
> > the cycle.
> Bad name. Something like "module_ctors_unordered" would be better (I don't
> like that one either, but this way it's at least clear what it does).

no_cyclic_imports would probably be better given that you're trying to get 
around a cyclic import, but I don't see what's unclear about cyclic_imports 
given that that's exactly what the runtime complains about when this problem 
occurs.

> but still has the problem that adding another module ctor
> can result is silent breakage.

That's actually a really good argument IMHO for having to put the pragma or 
attribute on every single static constructor in a module. True, it may be a 
bit annoying, but it would avoid silent breakage.

- Jonathan M Davis
November 29, 2012
Re: Fixing cyclic import static construction problems
On 2012-11-29 03:34, Walter Bright wrote:

> Add a pragma,
>
>      pragma(cyclic_imports);
>
> This can appear anywhere in a module, and applies globally to that module.
> It means that static constructors from imports that are not part of the
> cycle
> are run first, and that the static constructor for this module may be
> run before
> the static constructors of other modules that are part of the cycle.

I would think that "cyclic_imports" sounds like the static constructors 
are part of the cycle.

-- 
/Jacob Carlborg
November 29, 2012
Re: Fixing cyclic import static construction problems
On Thursday, 29 November 2012 at 03:19:55 UTC, Andrei 
Alexandrescu wrote:
> On 11/28/12 9:34 PM, Walter Bright wrote:
>> For discussion:
> [snip]
>
> I'd say we better finish const, immutable, and shared first.
>
> Andrei

+1

Fully agree.

Cyclic imports are a minor nuisance that can be easily solvable 
with better code architecture.

Turbo Pascal/Delphi is the only language that I know fully allows 
cyclic dependencies between modules. So this is not that 
important for most people.

--
Paulo
« First   ‹ Prev
1 2 3 4 5
Top | Discussion index | About this forum | D home