Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

Change Log: 2.090.0

previous version: 2.089.0

Download D nightlies
To be released

This changelog has been automatically generated from all commits in master since the last release.

  • The full-text messages are assembled from the changelog/ directories of the respective repositories: dmd, druntime, phobos, tools,, installer, and dub.
  • See the DLang-Bot documentation for details on referencing Bugzilla. The DAutoTest PR preview doesn't include the Bugzilla changelog.
  • The pending changelog can be generated locally by setting up and running the pending_changelog target:
    make -f posix.mak pending_changelog

2.090.0 comes with 6 major changes and 31 fixed Bugzilla issues. A huge thanks goes to the 35 contributors who made 2.090.0 possible.

List of all upcoming bug fixes and enhancements in D 2.090.0.

Compiler changes

  1. Deprecate allowing shadowing in foreach loops

    Up until this version it was allowed to shadow a variable in a foreach loop, although it is dissallowed in a normal for loop. This patch makes the behavior of the foreach loop consistent with the for loop one. To fix any issues encountered, rename the variable inside the foreach body that shadows the one from the upper scope.

  2. IsExpressions now correctly match combinations of const, inout, and shared.

    With Bugzilla 20138 fixed, IsExpressions now correctly match combinations of the qualifiers const, inout, and shared.

    Examples that failed previously but pass now:

    static assert(is(shared(const int) U == shared U) && is(U == const int));
    static assert(is(shared(inout int) U == inout U) && is(U == shared int));

    Note that the behavior of code like the following changes:

    static if (is(T U == const U) { ...}
    else static if (is(T U == shared const U)) { ... }

    The second case will never be reached, because the first one now matches when T is shared const. To get the old behavior, switch the order.

  3. Can now extract delegate from lazy parameter

    The underlying delegate of the lazy parameter may be extracted using the & operator:

    void test(lazy int dg)
        int delegate() dg_ = &dg;
        assert(dg_() == 7);
        assert(dg == dg_());
    void main()
        int a = 7;

    Previously this caused a compile error.

  4. extern(C) declarations in template mixins now mangle as C symbols when mixed in at global scope

    This was already true for string mixins, but since template mixins introduce a new scope, symbols inside them got mangled as D symbols. However, users often use extern(C) inside a mixin template to automatically generate boilerplate code that should be accessible from C.

    // library code
    mixin template WasmEntryPoint() {
        extern(C) export void _start() {
            // boilerplate code
    mixin template UseGpuInsteadOfIntegratedGraphics() {
        extern(C) export uint NvOptimusEnablement = 0x00000001;
        extern(C) export int AmdPowerXpressRequestHighPerformance = 1;
    // application code
    mixin WasmEntryPoint;
    mixin UseGpuInsteadOfIntegratedGraphics;
    static assert(_start.mangleof == "_start");
    static assert(NvOptimusEnablement.mangleof == "NvOptimusEnablement");

    Previously, _start would be mangled like _D9onlineapp8__mixin46_startUkZv and users had to manually add pragma(mangle, "_start") or use a string mixin instead. With the new behavior this is not necessary anymore for extern(C), as well as extern(Windows) and extern(Objective-C). extern(C++) remains unchanged since it already always mangles to C++, even in nested scopes.

    There is a possibility this breaks code if you mix in different extern(C) declarations with the same name in the global scope of multiple modules.

    import core.stdc.stdio;
    mixin template GenPrintCallback(string text) {
        auto textLength = text.length;
        auto textPointer = text.ptr;
        void callBackOnly() {
            printf("%.*s\n", textLength, textPointer);
        mixin(`auto `, text, ` = &callBackOnly;`);
    mixin GenPrintCallback!"foo";
    // in a different module:
    mixin GenPrintCallback!"bar";

    In this case textLength, textPointer and callBackOnly will be defined multiple times, so the linker either picks one or raises and error. The solution is to not make variables extern(C) and make C callback functions anonymous:

    import core.stdc.stdio;
    mixin template GenPrintCallback(string text) {
        auto textLength = text.length; // not below an extern(C): anymore
        auto textPointer = text.ptr;
        alias FunT = extern(C) void function();
        enum FunT callBackOnly = () {
            printf("%.*s\n", textLength, textPointer);
        mixin(`auto `, text, ` = callBackOnly;`);
  5. The default linker for the Digital Mars tool chain is now optlink.exe

    The default linker when building with -m32 under Windows has been changed from link.exe to optlink.exe to avoid calling the wrong linker when both the Digital Mars tool chain and the Microsoft compiler tools are found in the PATH environment variable.

  6. New -Xcc compiler flag to address issue 6952

    On POSIX, dmd passes -L-prefixed compiler flags through the linker driver (cc by default) to the linker (e.g. ld) by prepending them with -Xlinker. Therefore, it was not possible to pass flags directly to the linker driver.

    This release adds a new compiler flag, -Xcc, which specifies a flag to pass to the linker driver. This switch has already existed in the LDC compiler for several releases. Some use cases for it would be -nostartfiles, -pthread, and -static, which can now be specified as -Xcc=-nostartfiles, -Xcc=-pthread, and -Xcc=-static respectively.

    Note that it was previously also possible to specify linker driver options by setting the CC environment variable, e.g. CC='cc -pthread' dmd ..., or by setting the CC variable to point to a custom linker driver wrapper script. -Xcc improves on this through composability and better opportunities for integration into build systems.

    See also:

List of all bug fixes and enhancements in D 2.090.0:

DMD Compiler bugs

  1. Bugzilla 8684: Missing ')' in argument list creates a sea of error messages
  2. Bugzilla 20220: pragma(crt_constructor) does not work with clang 9
  3. Bugzilla 20318: Illegal instruction (core dumped)
  4. Bugzilla 20326: stringof on opaque type results in forward reference error
  5. Bugzilla 20367: Postblit cannot be disabled when copy ctor is defined
  6. Bugzilla 20400: CTFE increasing length of array of characters changes its value

DMD Compiler enhancements

  1. Bugzilla 11038: static has no effect as a block attribute for imports
  2. Bugzilla 20334: posix.mak clean target does not remove all generated files

Phobos bugs

  1. Bugzilla 10126: Make TaskPool terminate on its own or improve docs to make it clear that it won't
  2. Bugzilla 10448: min and max are not NaN aware
  3. Bugzilla 10902: some phobos unittests take an excessive amount of time
  4. Bugzilla 11013: ignoring variable inside the predicate of findSplitBefore
  5. Bugzilla 19283: [std.mathspecial] documentation for normal distribution doesn't list parameters
  6. Bugzilla 19626: RedBlackTree of an enum fails in unittest mode
  7. Bugzilla 20260: CustomFloat with 0 precision/exponentWidth
  8. Bugzilla 20261: CustomFloat.epsilon yields infinity
  9. Bugzilla 20263: Wrong value for CustomFloat.min_exp
  10. Bugzilla 20281: CustomFloat is limited to 64 bit
  11. Bugzilla 20282: CustomFloat.dig fails at some values.
  12. Bugzilla 20283: CustomFloat.max_exp not working in some cases
  13. Bugzilla 20284: CustomFloat.max_10_exp does not work for types with too many digits in exponent
  14. Bugzilla 20286: CustomFloat.min_normal fails, when not allowDenorm
  15. Bugzilla 20313: Inconsistent behavior of wouldHaveBlocked on Windows
  16. Bugzilla 20357: format should obey space flag when printing nan or inf

Phobos enhancements

  1. Bugzilla 20288: std.format double with NaN fails with range violation on comma

Druntime bugs

  1. Bugzilla 20299: checkaction=context not working with temporary destructors
  2. Bugzilla 20315: checkaction=context fails for const(void[]) argument
  3. Bugzilla 20322: checkaction=context fails for wstring/dstring arguments
  4. Bugzilla 20323: checkaction=context fails for non-copyable arguments
  5. Bugzilla 20346: std.uuid does not compile with checkaction=context

Tools bugs

  1. Bugzilla 20386: Test extractor shouldn't emit unit tests, but regular functions for @betterC tests

Contributors to this release (35)

A huge thanks goes to all the awesome people who made this release possible.

previous version: 2.089.0