version(Darwin) predefined

Posted 2026-06-01

We're still OpenD to common-sense, incremental improvements and this week, we shipped version(Darwin) as a pre-defined identifier to limit copy/pasta spam, all with minimal code breakage.

More...

version Darwin

A common file heading copy/pasted throughout both druntime and third party libraries that try to support the platforms produced by Apple Inc. is:

version (OSX)
    version = Darwin;
else version (iOS)
    version = Darwin;
else version (TVOS)
    version = Darwin;
else version (WatchOS)
    version = Darwin;

This block is repeated almost 100 times through druntime's source code because versions are either superglobal, defined by the compiler or on the build command line, or module-local. There's no middle ground; you cannot import a version from a shared file. (You can do enums and import them with static if but this leads to more order-of-evaluation issues in real world code; it kinda works but it is frequently buggy, so it doesn't work well in practice.) Thus, duplication was the only real choice for cases like this.

However, if the platforms are so similar you practically have to duplicate this block 100 times to get work done, couldn't the compiler do this for you? Just like it defines version(Posix) for you on these platforms?

Of course it can! And it now does in OpenD. But what about all that existing code the defines it? Since trying to define a reserved identifier is an error, is this going to break code? That's where the other part of the commit comes in:

- if (isReserved(ident))
+ if (isReserved(ident) && (global.versionids is null || !findCondition(global.versionids, Identifier.idPool(ident))))

In other words, if triggers that error only if it is a reserved name and $I(not already set by the compiler). If you try to set it where it is not already defined, it will issue the old error still. Thus, it ensures nothing accidentally changes, either you compile and get the same result as before, or you get a build error and can fix it.

You can see there was only one use of version=Darwin in all of druntime that had to be edited after this change, so it wasn't 100% compatible, but better than 99% and an easy fix. Much easier than having to copy/paste that block even once more! And also easier than changing the name to something else and having to find/replace it all over to something like version(Apple) instead.

The rule also applies to other predefined identifiers, which means we can use the same thing in the future to group things like, for example, the BSD family (though they may not have such a common core to begin with! needs to be checked before actioned, but it is possible).

I didn't actually remove those 800 of copy/pasta because it wasn't necessary, and it not being necessary is the point of the adjusted rule, but a patch of about +8 for -800 would indubitably spark joy to some! Only did the change last night, but thus far, I'm making a note here—great success.

Now it is tempting to define Linux in addition to linux under the same rule... hmmm....