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.1

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 13 major changes and 62 fixed Bugzilla issues. A huge thanks goes to the 44 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:

Runtime changes

  1. Platform dependent execinfo introspection added

    A new module (core.internal.execinfo) has been added for platform dependent execinfo detection. On every POSIX system which provides an execinfo implementation as part of its C runtime the appropriate implementation- dependent execinfo module will be imported automatically.

    Besides that, there is an opportunity for using external execinfo implementations built as separated libraries and linking DRuntime with them.

    IMPORTANT: On platforms with C runtime not providing execinfo functionality one should decide whether an external lib (e.g. libexecinfo) will be used, or not. If not, DRuntime should be built normally without any additional version ID, but with external lib exactly one of the following version IDs should be chosen at compile time. That means, the selected external format cannot be changed later without rebuilding DRuntime.

    It could be really important to keep this in mind when someone is packaging DRuntime for such OSs (e.g. ones using musl libc) and provide packages with and without execinfo support (with the specific external library as dependency) or in the case of source based packages, make this build option selectable (e.g. portage).

    Version IDBacktrace format
    ExtExecinfo_BSDFmt0x00000000 <_D6module4funcAFZv+0x78> at module
    ExtExecinfo_DarwinFmt1 module 0x00000000 D6module4funcAFZv + 0
    ExtExecinfo_GNUFmtmodule(_D6module4funcAFZv) [0x00000000] or module(_D6module4funcAFZv+0x78) [0x00000000] or module(_D6module4funcAFZv-0x78) [0x00000000]
    ExtExecinfo_SolarisFmtobject'symbol+offset [pc]

    These formats above cover most of the "classic" backtrace outputs but as a new important format emerges, it can be easily added.

  2. Added intrinsic toPrec to round to a specific float precision

    The intrinsic core.math.toPrec forces rounding of it floating point argument to the precision of float, double, or real.

    Some floating point algorithms, such as Kahan-Babuska-Neumaier Summation, require rounding to specific precisions. Rounding to precision after every operation, however, loses overall precision in the general case and is a runtime performance problem.

    Adding these functions guarantee the rounding at required points in the code, and document where in the algorithm the requirement exists.

Library changes

  1. Deprecated std.array.Appender.toString was removed

    The overload accepting a callable was deprecated since 2.079 and has now been removed. Use the overload accepting an output range instead.

  2. Deprecated std.functional.binaryReverseArgs was removed

    This specialisation of reverseArgs accepting exactly two arguments was deprecated since 2.079 and has now been removed. Use reverseArgs instead.

  3. Deprecated std.bitmanip.BitArray.toString was removed

    The overload accepting a callable was deprecated since 2.079 and has now been removed. Use the overload accepting an output range instead.

  4. Deprecated module std.experimental.all was removed

    All symbols contained in Phobos can now be used with import std

  5. Added get!(T) getter to std.json

    This getter will try to return underlying json type as T if possible. It is convenient for automatic integer conversion like this:

    import std.json;
    string s = `{ "a": 123 }`;
    auto json = parseJSON(s);
    // This will throw with json["a"].floating
    assert(json["a"].get!double == 123.0);

List of all bug fixes and enhancements in D 2.090.0:

DMD Compiler regressions

  1. Bugzilla 20418: Unittest failure in bitarray.d on Win32

DMD Compiler bugs

  1. Bugzilla 6592: di header file created even if errors occur
  2. Bugzilla 8684: Missing ')' in argument list creates a sea of error messages
  3. Bugzilla 9490: 'this' is not found when expression is in parentheses
  4. Bugzilla 10562: Cannot initialize arrays by an element value when the elements are fixed-length arrays
  5. Bugzilla 14696: destructor for temporary called before statement is complete with conditional operator
  6. Bugzilla 17125: Header Generation Incorrectly Formats Floating Point Number
  7. Bugzilla 19432: Cannot initialize ulong with decimal value above signed long range
  8. Bugzilla 20220: pragma(crt_constructor) does not work with clang 9
  9. Bugzilla 20318: Illegal instruction (core dumped)
  10. Bugzilla 20326: stringof on opaque type results in forward reference error
  11. Bugzilla 20367: Postblit cannot be disabled when copy ctor is defined
  12. Bugzilla 20400: CTFE increasing length of array of characters changes its value
  13. Bugzilla 20401: ref variable copied before return
  14. Bugzilla 20406: Copy constructor requires default constructor
  15. Bugzilla 20413: C++ mangling bug with templates & the std namespace
  16. Bugzilla 20417: __traits(compiles) returns false result if expression is not wrapped inside a lambda while typeof works correctly
  17. Bugzilla 20419: is(missing == module/package) results in unknown identifier

DMD Compiler enhancements

  1. Bugzilla 4544: Better error-message when expecting string but got a character constant
  2. Bugzilla 11038: static has no effect as a block attribute for imports
  3. Bugzilla 18809: Improve error message on nonexistent property
  4. Bugzilla 20334: posix.mak clean target does not remove all generated files

Phobos bugs

  1. Bugzilla 9588: format prints context pointer for struct
  2. Bugzilla 9592: Justified Tuple printing
  3. Bugzilla 10126: Make TaskPool terminate on its own or improve docs to make it clear that it won't
  4. Bugzilla 10448: min and max are not NaN aware
  5. Bugzilla 10902: some phobos unittests take an excessive amount of time
  6. Bugzilla 11013: ignoring variable inside the predicate of findSplitBefore
  7. Bugzilla 11782: format pointer to range prints range
  8. Bugzilla 15940: ImplicitConversionTargets and class alias in struct
  9. Bugzilla 16223: BigUint: undefined shift for small instantiation type
  10. Bugzilla 18248: radix overload of std.conv.parse fails to throw on non-empty range without number
  11. Bugzilla 18446: Wrong curl onProgress examples
  12. Bugzilla 19283: [std.mathspecial] documentation for normal distribution doesn't list parameters
  13. Bugzilla 19626: RedBlackTree of an enum fails in unittest mode
  14. Bugzilla 19733: expi documentation links broken
  15. Bugzilla 20160: ThreadInfo.cleanup() clears local thread's registered names instead of "this"'s
  16. Bugzilla 20260: CustomFloat with 0 precision/exponentWidth
  17. Bugzilla 20261: CustomFloat.epsilon yields infinity
  18. Bugzilla 20263: Wrong value for CustomFloat.min_exp
  19. Bugzilla 20281: CustomFloat is limited to 64 bit
  20. Bugzilla 20282: CustomFloat.dig fails at some values.
  21. Bugzilla 20283: CustomFloat.max_exp not working in some cases
  22. Bugzilla 20284: CustomFloat.max_10_exp does not work for types with too many digits in exponent
  23. Bugzilla 20286: CustomFloat.min_normal fails, when not allowDenorm
  24. Bugzilla 20313: Inconsistent behavior of wouldHaveBlocked on Windows
  25. Bugzilla 20314: passing const variables to only forces const range element type
  26. Bugzilla 20357: format should obey space flag when printing nan or inf
  27. Bugzilla 20396: format!"%a" leeds to wrong result for denormalized float
  28. Bugzilla 20398: Wrong number of totalEntries in
  29. Bugzilla 20408: style checker should not check backup files

Phobos enhancements

  1. Bugzilla 20198: Make std.math.nextUp and nextDown and nextafter work in CTFE for float and double
  2. Bugzilla 20288: std.format double with NaN fails with range violation on comma
  3. Bugzilla 20425: Proxy opCmp fails to compile with types that overloaded opCmp
  4. Bugzilla 20439: memoize fails with types that have a void opAssign

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
  6. Bugzilla 20364: [REG2.069] changing length for typeof(null)[] array seg faults in _d_arraysetlengthiT()
  7. Bugzilla 20440: Associative arrays with values whose opAssign doesn't return a ref don't support require function

Contributors to this release (44)

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

previous version: 2.089.1