Bug 14517 – Templated static ctor + separate compilation = module cycles

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-04-28T19:41:54Z
Last change time
2024-12-13T18:42:38Z
Assigned to
No Owner
Creator
Steven Schveighoffer
Moved to GitHub: dmd#17706 →

Comments

Comment #0 by schveiguy — 2015-04-28T19:41:54Z
Even though druntime plays a role, I'm marking this as DMD, since druntime cannot figure this out without compiler help. Example: mod1.d ========== module mod1; import std.stdio; struct S(T) { shared static T t; shared static this() {writeln(T.stringof); _t = 5;} } void main() {} mod2.d ========== module mod2; import mod1; import mod3; S!int x; mod3.d ========== module mod3; import mod1; import mod2; S!int x; command line ==== dmd mod1.d mod2.d mod3.d ./mod1 int dmd -c mod2.d dmd -c mod3.d dmd mod1.d mod2.o mod3.o ./mod1 object.Exception@src/rt/minfo.d(162): Aborting: Cycle detected between modules with ctors/dtors: mod2 -> mod3 -> mod2 ================ Note that the module ctor only runs once (I only see one printout of 'int'), so at least that is figured out at runtime. Examination of the module info using druntime debugging printfs shows that in the first case (when all 3 modules are compiled at once), mod1 is marked as having a static CTOR, mod2 and 3 are not. In the second case, mod1 is not marked as having a static ctor, mod2 and mod3 are. I wonder if a separate "linkage" module info with just the static ctors dependent on both modules should be created with a dependency on the instantiating and the template module could be created, which should eliminate any issues (it's definitely possible right now to construct a cycle between instantiating and template modules). The instantiating module should have a dependency on the linkage module as well, since there could be a cycle there also! It's a very complex issue, but probably not very common.
Comment #1 by issues.dlang — 2015-04-28T20:05:44Z
Comment #2 by schveiguy — 2015-04-28T20:20:46Z
It's not a blocker, as we can work around that, see my new comments in the PR.
Comment #3 by code — 2015-04-28T21:36:18Z
You probably learned that for C++, avoid static constructors because the initialization order quickly becomes a mess. The problem here is that both mod2 and mod3 depend on a constructor, but also have a cyclic dependency. We could somehow (using linker tricks) try to push the ctors/dtors into mod1. I'm not sure I understand your idea Steven.
Comment #4 by schveiguy — 2015-04-28T22:16:16Z
If you look at PR 990 that Jonathan linked, you will see that it's not so cut and dry. Essentially ANY separate compiled module that imports another module that has some template constructors, even if they aren't used in that module, but used somewhere else, will flag that module as having ctors. The test I ran showed modules like std.traits having module bits flipped on because of core.time having static ctors in an instantiated template. That makes no sense whatsoever -- there's not even an instantiation of MonoTimeImpl in std.traits. Let me first say that we need to fix this regardless of how it's done or how complete the fix is. We absolutely cannot mark some module as having static ctors because of modules somewhere else in the import chain that have nothing to do with the given module. If this means banning static ctor/dtor in templates, so be it (though I think that's a bit difficult to swallow). And thinking some more about my idea, I don't think it will work. What we likely need is a way to say that mod2 or mod3 can "upgrade" mod1's bit (at runtime). Perhaps we can discuss at dconf '15.
Comment #5 by bugzilla — 2015-07-02T22:05:43Z
Comment #6 by pro.mathias.lang — 2020-08-06T11:08:15Z
This might be related to https://issues.dlang.org/show_bug.cgi?id=20641 which triggers with separate compilation + module ctors in templated code.
Comment #7 by robert.schadek — 2024-12-13T18:42:38Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17706 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB