Fixing cyclic import static construction problems

Jonathan M Davis jmdavisProg at gmx.com
Thu Nov 29 13:43:10 PST 2012


On Thursday, November 29, 2012 16:18:10 Paulo Pinto wrote:
> On Thursday, 29 November 2012 at 12:04:28 UTC, Max Samukha wrote:
> > On Thursday, 29 November 2012 at 11:39:20 UTC, Paulo Pinto
> > 
> > wrote:
> >> 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.
> > 
> > Show me please how to solve that problem easily with acceptable
> > results, would you?
> 
> You just need to have a better architecture.
> 
> In 20 years of software development experience I never found a
> case were this wasn't possible.
> 
> Maybe you care to provide an example?

Considering that you need static constructors to initialize any static 
variables at runtime (and in the case of const and immutable variables, you 
_can't_ work around that by doing the initialization later - it _must_ be in 
the static constructor), and all it takes for the compiler to declare a 
circular import is to have two modules import each other - even indirectly - 
it becomes extremely easy to run into this problem. And if you're dealing with 
immutable static variables which are initialized at runtime, you can't fix it 
unless you can contort your modules so that they don't depend on each other, 
and with a lot of modules, that can become extremely difficult. We had to strip 
out all static constructors from std.datetime because of this, and in order to 
fix it, we had to do some nasty voodoo with casting in order to lazily 
initialize some variables which are supposed to be immutable. _None_ of that 
sort of thing should be necessary. As it stands, it's basically bad practice 
to use static constructors, because it's so easy to end up with circular 
dependencies, and they can involve modules which don't seem even vaguely 
related because of other stuff that they import and are often a royal pain to 
debug and fix, if you even can without seriously revamping your design. And for 
a library like Phobos which needs to avoid breaking backwards compatibility, 
redesigning things to avoid such circular dependencies isn't necessarily even 
possible, because those redesigns would break backwards compatibliity.

We _need_ a solution for this. Whether now is the best time tackle it is 
another matter, but the current situation with static constructors is 
ridiculous. There are features which require them, but you have to avoid them 
or you're going to run into circular dependency issues very easily.

This is a case of some great design decisions in D have leading to a very bad 
design, and it needs to be fixed. Fortunately, it shouldn't be all that hard to 
fix with an attribute of some kind. But prior to now, Walter wouldn't even 
consider it. I do think though that the idea of using only one pragma instead 
of an attribute/pragma per static constructor is a bad idea because of the 
silent breakage that it would cause, as has been pointed out in this thread. 
So, his proposed solution needs some tweaking.

- Jonathan M Davis


More information about the Digitalmars-d mailing list