Pitch: `@globalConstructor`

If this were to go in, I would prefer to see the constructor priority redesigned to state dependencies rather than just list a number. Contributors who've been hanging around Evolution since 2016 might remember that operator precedence was originally expressed with raw integers in a similar fashion, and SE-0077's introduction of precedence groups which were described relative to each other dramatically improved the situation. If we took on this feature, I would hope to see something similar here—perhaps you would say things like @globalConstructor(after: first) func second().

But that's burying the lede, which is that I agree with John. I'm very skeptical of global constructors or other features that automatically run code on launch, and I believe we'd be better off designing lower-overhead features for specific important use cases. For example, your proposal mentions registering plug-ins; that job is probably better done by adding a special metadata section to binaries that lists conformances for protocols that have requested registration, and providing APIs that allow for incremental scanning of this metadata after new dynamic libraries are loaded into the process. Similarly, your library configuration use case could be better handled by repurposing the existing lazy global initialization mechanism to run configuration code on the first use of a library. Mechanisms like these delay the setup costs until they actually need to be incurred, which shifts those costs away from busy process launch phases and often avoids incurring them at all.

17 Likes