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