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

previous version: 2.088.1 – next version: 2.089.1

Download D 2.089.0
released Nov 02, 2019

2.089.0 comes with 11 major changes and 66 fixed Bugzilla issues. A huge thanks goes to the 44 contributors who made 2.089.0 possible.

Library changes

  1. Added std.traits.Unconst

List of all bug fixes and enhancements in D 2.089.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. 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;`);
  4. 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.

  5. 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. Added core.atomic.atomicFetchAdd and core.atomic.atomicFetchSub.

    Added core.atomic.atomicFetchAdd and core.atomic.atomicFetchSub to the atomic suite.

  2. Make wstatus predicates pure and @safe

    The predicates that operate on the wstatus value reported by wait(2) are now marked pure and @safe, allowing them to be used in functions with those attributes.

Library changes

  1. Added std.traits.Unconst

    std.traits.Unconst works like std.traits.Unqual, but removes only const, inout and immutable qualifiers from a type.

Dub changes

  1. Improved support for LDC, incl. cross-compilation

    The ldc2 driver now supports

    • some more command-line options (coverage, profiling, keeping stack frame),
    • separate linking,
    • cross-compilation by specifying the target triple (LDC -mtriple) as --arch, e.g., --arch=x86_64-pc-windows-msvc. Check out for how to setup LDC.

  2. Lint command added

    Dub supports now command lint, which will execute D-Scanner on the dub package. By default dub lint will execute style check. Import paths to dependent dub packages will be passed to D-Scanner.

    dub lint

  3. Added SemVer compatibility operator "^"

    Dub now supports version specifications of the form ^x.y.z. This corresponds to a "semver compatible version", ie. any version up from x.y.z with the same major number. If the major number is 0, only the same version matches. This corresponds to the versions listed on as compatible with the public API of the version given. ^x.y is equivalent to ^x.y.0.

List of all bug fixes and enhancements in D 2.089.0:

DMD Compiler regressions

  1. Bugzilla 20126: codegen reloads parameter from register when iasm changed the backing memory
  2. Bugzilla 20212: invalid debug info with enum type in library

DMD Compiler bugs

  1. Bugzilla 982: Codeview: symbols of enum type are declared integer
  2. Bugzilla 1104: CodeView: char is marked 0x20 (T_UCHAR) instead of 0x10 (T_CHAR)
  3. Bugzilla 2195: Variable shadowing in foreach is not detected and reported
  4. Bugzilla 2450: Error using operators from named template mixin
  5. Bugzilla 3831: writeln of a delegate typeid
  6. Bugzilla 4372: type of enumerator values reduced to base type in debug info
  7. Bugzilla 6952: Static Linking on Linux
  8. Bugzilla 13582: Deprecated modules imported from other deprecated modules shouldn't be warned about
  9. Bugzilla 16047: Range violation in setting multi-dimensional AA entries
  10. Bugzilla 19965: [DIP1000] Template allows to escape internal pointer
  11. Bugzilla 20012: extern(C) functions inside template mixins are not mangled as C functions
  12. Bugzilla 20089: FPU stack not cleaned up properly
  13. Bugzilla 20131: Bad codegen from inline asm LOCK CMPXCHG; possible REX prefix missing
  14. Bugzilla 20138: is expression not evaluating correctly?
  15. Bugzilla 20163: Deprecated import in string mixin does not output diagnostic message
  16. Bugzilla 20164: Importing deprecated module at function-local scope does not output diagnostic message
  17. Bugzilla 20181: [nightly 2019-08-29] internal compiler error when static foreach iterating property method of struct
  18. Bugzilla 20244: New dmd option -preview=noXlinker does not work on Linux to build a simple D application
  19. Bugzilla 20267: Error: string is used as a type - and similar “smart” error messages

DMD Compiler enhancements

  1. Bugzilla 809: Should be possible to convert lazy argument to delegate
  2. Bugzilla 1547: Default parameter values should use implicit static opCall
  3. Bugzilla 3004: [patch] Better handling of ignored pragmas
  4. Bugzilla 15118: Have dmd on Win32 look for optlink.exe instead of link.exe
  5. Bugzilla 18272: missing changelog entry and no doc for -gf (besides cryptic emit debug info for all referenced types)
  6. Bugzilla 18617: need __traits(deprecated, expr) to check whether an expression would trigger deprecation

Phobos regressions

  1. Bugzilla 20186: File size of "Hello, world" executable increased by 185KB
  2. Bugzilla 20295: zip64 with 0xff bytes in end of central dir record do not work
  3. Bugzilla 20328: [REG 2.089 beta] deprecation message about Nullable.get in isInputRange

Phobos bugs

  1. Bugzilla 15230: Inconsistent std.range.SortedRange predicate checks
  2. Bugzilla 17705: std.math.isFinite cannot run at compile-time
  3. Bugzilla 19514: gcd(BigInt(2), BigInt(1)) fails
  4. Bugzilla 20027: susceptible to zip malware attacks
  5. Bugzilla 20145: Random unittest failures inf std.datetime.stopwatch
  6. Bugzilla 20205: std.math: Wrong result for abs(int.min)
  7. Bugzilla 20218: Checked format string takes infinite time for infinite ranges
  8. Bugzilla 20239: chameleon zip-file should be rejected by
  9. Bugzilla 20240: BitArray inconsistently preserves bits past length
  10. Bugzilla 20241: BitArray.bitsSet ignores length
  11. Bugzilla 20287: Wrong compressed data
  12. Bugzilla 20301: std.regex.regex doesn't accept a const/immutable array of patterns
  13. Bugzilla 20302: std.functional.memoize doesn't accept a functions with const/immutable parameters

Phobos enhancements

  1. Bugzilla 20147: Enable comparison (==, >, >=, <=, <) between std.bigint.BigInt and floating point numbers
  2. Bugzilla 20159: Make std.math.scalbn work in CTFE
  3. Bugzilla 20192: Make std.math.isSubnormal work in CTFE
  4. Bugzilla 20196: Make std.math.isNormal work in CTFE
  5. Bugzilla 20199: Make std.math.frexp work in CTFE
  6. Bugzilla 20200: Make std.math.isPowerOf2 work for floating point numbers in CTFE
  7. Bugzilla 20201: Make std.math.scalbn pure
  8. Bugzilla 20202: Make std.math.signbit work in CTFE
  9. Bugzilla 20203: Make std.math.copysign work in CTFE
  10. Bugzilla 20242: BitArray constructor should not modify input data

Druntime regressions

  1. Bugzilla 20270: [REG2.087] Deadlock in garbage collection when running processes in parallel

Druntime bugs

  1. Bugzilla 13821: fiber + exception + win server 2012 failures
  2. Bugzilla 16380: no bindings for err.h
  3. Bugzilla 18643: Compiling error when combining CAS and numeric literal.
  4. Bugzilla 19481: Aborting from local/libphobos/libdruntime/core/sync/mutex.d(95) Error: pthread_mutex_init failed.
  5. Bugzilla 20155: Allocating a struct with dtor on the GC heap can produce false pointers
  6. Bugzilla 20214: GC: realloc can result in false pointers if address doesn't change

Druntime enhancements

  1. Bugzilla 8831: core.atomic: add compare-and-swap function with other result type
  2. Bugzilla 13826: Move volatileLoad/Store to core.volatile when the volatile keyword is removed
  3. Bugzilla 15007: core.atomic match C++11
  4. Bugzilla 20105: core.atomic 'cas' function is incomplete
  5. Bugzilla 20106: core.atomic : atomicFence doesn't accept MemoryOrder
  6. Bugzilla 20107: core.atomic : Memory order is missing keys

Contributors to this release (44)

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

previous version: 2.088.1 – next version: 2.089.1