Pitch: `@globalConstructor`

This is something we've been trying to avoid in the language. There's a couple reasons for that:

  • The first is that global constructors have an inherent ordering problem. Global constructors often end up having dependencies on other global constructors, and solving that well is sort of a pit of complexity, especially without elaborate toolchain support.

  • The second is that global constructors are inherently very brittle because by design they precede all normal user code (other than other global constructors, as discussed above). In particular, global construction very tightly constrains how the subsystem can be configured — it has to be configured by things like environment variables because normal command-line arguments are usually not available. And then that means the global constructor is very heavyweight, which feeds into the next problem.

  • The third is that global constructors are eagerly run, which means they impose substantial launch-time penalties on the program even if the subsystem they're part of it is never used. Subsystem designers have a tendency to think of their subsystem as being centrally important to the overall program, and so anything that makes the subsystem simpler or more performant is worthwhile. This is often much less true in practice.

These arguments are why Swift has always pushed designs where initialization is lazy on first use. What we have is not perfect — in particular, it doesn't completely solve the configuration problem — but I think it's a better basis for the language than phased global construction.

I'm not going to say that your pitch is a non-starter, but these are the issues you need to address before I think we can consider it.

37 Likes