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.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, dlang.org, 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 dlang.org and running the pending_changelog target:
    make -f posix.mak pending_changelog


2.089.0 comes with 29 major changes and 73 fixed Bugzilla issues. A huge thanks goes to the 45 contributors who made 2.089.0 possible.

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

Compiler changes

  1. D1 operator overloads have been deprecated.

    The following D1 operator overloads have been deprecated in favor of opUnary:

    • opNeg Replace with opUnary(string op)() if (op == "-")
    • opCom Replace with opUnary(string op)() if (op == "~")
    • opPostInc Replace with opUnary(string op)() if (op == "++")
    • opPostDec Replace with opUnary(string op)() if (op == "--")
    • opStar Replace with opUnary(string op)() if (op == "*")

    The following D1 operator overloads have been deprecated in favor of opBinary:

    • opAdd Replace with opBinary(string op)(...) if (op == "+")
    • opSub Replace with opBinary(string op)(...) if (op == "-")
    • opMul Replace with opBinary(string op)(...) if (op == "*")
    • opDiv Replace with opBinary(string op)(...) if (op == "/")
    • opMod Replace with opBinary(string op)(...) if (op == "%")
    • opAnd Replace with opBinary(string op)(...) if (op == "&")
    • opXor Replace with opBinary(string op)(...) if (op == "^")
    • opOr Replace with opBinary(string op)(...) if (op == "|")
    • opShl Replace with opBinary(string op)(...) if (op == "<<")
    • opShr Replace with opBinary(string op)(...) if (op == ">>")
    • opUShr Replace with opBinary(string op)(...) if (op == ">>>")
    • opCat Replace with opBinary(string op)(...) if (op == "~")
    • opIn Replace with opBinary(string op)(...) if (op == "in")

    The following D1 operator overloads have been deprecated in favor of opBinaryRight:

    • opAdd_r Replace with opBinaryRight(string op)(...) if (op == "+")
    • opSub_r Replace with opBinaryRight(string op)(...) if (op == "-")
    • opMul_r Replace with opBinaryRight(string op)(...) if (op == "*")
    • opDiv_r Replace with opBinaryRight(string op)(...) if (op == "/")
    • opMod_r Replace with opBinaryRight(string op)(...) if (op == "%")
    • opAnd_r Replace with opBinaryRight(string op)(...) if (op == "&")
    • opXor_r Replace with opBinaryRight(string op)(...) if (op == "^")
    • opOr_r Replace with opBinaryRight(string op)(...) if (op == "|")
    • opShl_r Replace with opBinaryRight(string op)(...) if (op == "<<")
    • opShr_r Replace with opBinaryRight(string op)(...) if (op == ">>")
    • opUShr_r Replace with opBinaryRight(string op)(...) if (op == ">>>")
    • opCat_r Replace with opBinaryRight(string op)(...) if (op == "~")
    • opIn_r Replace with opBinaryRight(string op)(...) if (op == "in")

    The following D1 operator overloads have been deprecated in favor of opOpAssign:

    • opAddAssign Replace with opOpAssign(string op)(...) if (op == "+")
    • opSubAssign Replace with opOpAssign(string op)(...) if (op == "-")
    • opMulAssign Replace with opOpAssign(string op)(...) if (op == "*")
    • opDivAssign Replace with opOpAssign(string op)(...) if (op == "/")
    • opModAssign Replace with opOpAssign(string op)(...) if (op == "%")
    • opAndAssign Replace with opOpAssign(string op)(...) if (op == "&")
    • opOrAssign Replace with opOpAssign(string op)(...) if (op == "|")
    • opXorAssign Replace with opOpAssign(string op)(...) if (op == "^")
    • opShlAssign Replace with opOpAssign(string op)(...) if (op == "<<")
    • opShrAssign Replace with opOpAssign(string op)(...) if (op == ">>")
    • opUShrAssign Replace with opOpAssign(string op)(...) if (op == ">>>")
    • opCatAssign Replace with opOpAssign(string op)(...) if (op == "~")

    Starting with this release, any D code that triggers a lowering to the D1 operator overloads will emit a deprecation warning.

    Example of deprecation warning:

    struct S
    {
        int opAdd(int i) { ... }
    }
    
    void main()
    {
        S s;
        int i;
        i = s + 1;  // Deprecation: `opAdd` is deprecated.  Use `opBinary` instead.
    }
    

    Example of corrective action:

    struct S
    {
        int opBinary(string op)(int i) if (op == "+") { ... }
    }
    
    void main()
    {
        S s;
        int i;
        i = s + 1;  // OK
    }
    
  2. Deprecate allowing a constructor declaration in a static block

    The language specification states that a static constructor is defined using the construction static this(). Defining a constructor inside a static block does not have any effect on the constructor. The following code does not affect the constructor in any way:

    static:
        this() {}
    
    static
    {
        this() {}
    }
    

    The compiler does not issue any warning/error on the above code samples and generates a normal constructor which is not ran before the main function. This leads to situations in which the compiler is not able to correctly indicate the problem:

    class A
    {
        static
        {
            this() {}
        }
    
        this() {}
    }
    
    void main()
    {
        new A();
    }
    

    This code will result in an error message indicating that there is a multiple definition of the constructor this() which is a misleading message.

    Beginning with this release, whenever a constructor is encountered in a static context an error message is emitted stating that the static keyword does not have any effect on the constructor. The solution is to declare the constructor outside the static block either as a normal constructor or a static one (static this()).

  3. deprecated now applies to alias this as well

    Before this release, deprecated on alias this was accepted by the parser but did not trigger a deprecation mesage on usage.

  4. Double initialization of immutable fields inside constructor is now obsolete

    Inside a constructor scope, assigning to aggregate declaration (class/struct) members is done by considering the first assignment as initialization and subsequent assignments as modifications of the initially constructed object. For const/immutable fields the initialization is accepted in the constructor, but subsequent modifications are not. Example:

    class A
    {
        int a;
        immutable int b;
        this(int a, int b)
        {
            this.a = a;
            this.b = b;
    
            this.a = 7; // OK, a is mutable
            this.b = 9; // Error: immutable field b initialized multiple times
        }
    }
    

    However, Bugzilla 18719 shows that this rule does not apply when inside a constructor scope there is a call to a different constructor:

    class A
    {
        immutable int a;
        this()
        {
            this(42);
            this.a = 5;  // second initialization of immutable field
        }
    
        this(int a)
        {
            this.a = a;
        }
    }
    

    The above code wrongfully compiled succesfully before this patch, accepting the double initialization of the immutable field a. Starting with this release, this.a = 5 will emit an error stating that a is initialized multiple times.

  5. add __traits(getLocation, symbol)

    Takes one argument which is a symbol. Returns a tuple(string, int, int) whose entries correspond to the filename, line number and column number where the argument was declared.

    To disambiguate between overloads, pass the result of getOverloads with the desired index, to getLocation:

    module m;
    int foo();
    int foo(int);
    enum loc = __traits(getLocation, __traits(getOverloads, m, "foo")[0]);
    
  6. Suppress the "read-modify-write" error if type is a struct or a class

    If a struct or class with shared type implements the opUnary or opOpAssign operator then it is possible to perform "read-modify-write" operations because the operator's implementation is supposed to perform atomic operations.

    The purpose of this modification is to allow the creation of wrappers (with structs or classes) to run atomic operations silently, for example:

    shared struct Atomic {
        int a;
    
        int opUnary(string s)() if (s == "++")
        {
            import core.atomic : atomicOp;
            return atomicOp!"+="(a, 1);
        }
    }
    
    Atomic atomicvar;
    atomicvar++; // Safe! Atomic struct implements opUnary
    
  7. Postblit and destructors are no longer called on members of anonymous unions.

    Due to a bug in dmd, members of anonymous unions inside struct declarations had their postblits/destructors called when an object of the containing struct type was copied/destroyed. With this release, the postblit/destructor is no longer called in such situations.

    Fixes: https://issues.dlang.org/show_bug.cgi?id=19122

Runtime changes

  1. core.atomic : msync has been removed

    It had been deprecated in 2.061 in favor of MemoryOrder.

  2. Added overloads for core.atomic.cas which don't discard their result.

    Existing core.atomic.cas functions discard the result, which make it impossible to implement certain operations. A new set of overloads was added which take ifThis by pointer and write the result back to the argument.

  3. Added core.atomic.atomicExchange.

    Added missing core.atomic.atomicExchange function to the atomic suite.

  4. Non-POSIX CLOCK enum members have been removed from core.sys.posix.time

    Namely CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_COARSE (linux), CLOCK_MONOTONIC_PRECISE, CLOCK_MONOTONIC_FAST (FreeBSD, DragonflyBSD), and CLOCK_MONOTONIC_COARSE (CRuntime_Glibc). Those were deprecated in 2.067. They are available on their respective platform modules.

  5. The druntime option callStructDtorsDuringGC has been deprecated.

    Starting with this release utilizing the callStructDtorsDuringGC runtime option will result in a deprecation message printed to stderr. The option will be removed in a future release.

  6. core.sys.posix.dlfcn : dladdr, dlvsym, Dl_info have been removed

    They are linux extensions, not POSIX, and thus can be found in core.sys.linux.dlfcn. They had been deprecated since 2.063.

  7. core.exception: Remove onHiddenFuncError / HiddenFuncError

    Those have been deprecated since 2.068, and are related to a language feature that is long gone.

  8. core.exception : setAssertHandler has been removed

    It had been deprecated in 2.064 in favor of assertHandler.

  9. core.thread : Fiber.call(bool) has been removed

    This had been deprecated since 2.068 in favor of Fiber.call(Rethrow.[Yes|No]).

  10. Module core.sys.linux.sys.netinet.tcp has been removed

    This module had been deprecated since 2.077.0. core.sys.linux.netinet.tcp should be imported instead.

  11. core.runtime : Runtime.initialize, Runtime.terminate functions taking ExceptionHandler have been removed

    They were deprecated since 2.065 in favor of rt_init C functions, which allow to initialize the runtime from C code.

  12. Added core.stdcpp.string.

    Added core.stdcpp.string, which links against C++ std::basic_string

    Known issues:

    Currently, the GCC (libstdc++) implementation has a known issue with the modern __cxx11 ABI, because the C++ struct contains an interior pointer which is illegal in D, and incompatible with D move semantics. To use core.stdcpp.string on linux/GCC, you must use the old string ABI by supplying -D_GLIBCXX_USE_CXX11_ABI=0 to g++, and also -version=_GLIBCXX_USE_CXX98_ABI to your D compiler. Work to define D move constructors is ongoing and expected to resolve this issue when it arrives.

  13. Added core.stdcpp.vector.

    Added core.stdcpp.vector, which links against C++ std::vector

Library changes

  1. std.array.Appender and RefAppender: use .opSlice() instead of data()

    Previonsly, Appender.data() was used to extract a slice of the Appender's array. Now use the [] slice operator instead. The same goes for RefAppender.

    std.array.Appender std.array.RefAppender

  2. ErrnoException.errno is now nothrow pure @nogc @safe

    Before, it was just @system. As it turns out, all it does is return the value of an integer field, so it can have all these attributes.

  3. Nullable alias get this has been deprecated

    Nullable's feature of implicitly converting to its contained value has been marked deprecated.

    All sites where a Nullable!T is implicitly converted to T, potentially throwing an error at runtime, will now produce a deprecation warning or error with -de.

    To fix this, explicitly use .get to access the contained value of the Nullable.

    alias get this is the only implicit conversion in D that may throw an error. Since it is an implicit conversion, it can easily be used accidentally and lead to unexpected runtime errors. By explicitly invoking get, the developer acknowledges that the operation has a chance of error. Conversely, by not implicitly converting Nullable!T to T, the compiler gives the developer a chance to spot forgotten isNull checks.

    This feature will be removed after release 2.096.

  4. Added the std.file.getAvailableDiskSpace functionality.

    std.file.getAvailableDiskSpace receives as a parameter the path of a file or directory in the file system, and returns the available disk space on the mounted filesystem. If the given path is nonexistent, an exception is thrown.

    import std.file;
    ulong size = getAvailableDiskSpace(".");
    assert(size > 0);
    
    import std.file;
    assertThrown(getAvailableDiskSpace("NonExistentFile"));
    
  5. Allow std.json to overlook trailing comma

    The JSON grammar does not allow trailing commas, however they are accepted by many JSON parsers. std.json now ignores trailing commas as well. Use JSONOptions.strictParsing to disable this behavior.

    import std.json;
    import std.exception : assertThrown, assertNotThrown;
    
    // before
    assertThrown(parseJSON(`{ "a" : { } , }`));
    
    // after
    assertNotThrown(parseJSON(`{ "a" : { } , }`));
    

Installer changes

  1. Bundled libcurl is now built with DONT_USE_RECV_BEFORE_SEND_WORKAROUND

    The bundled libcurl is now build with DONT_USE_RECV_BEFORE_SEND_WORKAROUND. See #399 for details.

Dub changes

  1. Builds dynamicLibrary targets as dynamic libraries instead of static libraries.

    Dub will no longer build dynamicLibrary targetType's as staticLibrary.

    Except for x86_omf. This has been disabled due to numerous issues that will lead this to not doing what is expected of it.

    No compiler or linker flags have been added at this time, you will need to specify the relevant flag to get the compiler to link dynamically against Phobos.

  2. The $DUB_BUILD_PATH variable was added

    The $DUB_BUILD_PATH variable is now defined inside the postBuildCommands section. It contains the absolute path in which the package was built, and can be used to copy by-products of the build process to their intended locations.

    For example, if an executable exports symbols, you will want to make the resulting import library and symbols export file available somewhere. That can be done with a dub.json section like this:

        "postBuildCommands-windows": [
            "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.lib $PACKAGE_DIR\\lib"
            "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.exp $PACKAGE_DIR\\lib"
        ],
    
  3. Command environment variable substitution changed

    Now users can use the documented predefined variables inside custom command directives without the need for a wrapper shell script.

    Before this would have failed:

    "preBuildCommands": ["$DC -run foo.d"]
    
    unless DC was defined as environment variable outside DUB.

    It was before possible to run a script that used the $DC environment variable or on POSIX escape the $ with $$DC to make the shell substitute the variable. These workarounds are no longer needed now.

    API change: none of the different command directives are no longer substituted with the process environment variables. You now access the raw commands as provided by the user in the recipe. dub describe has been adjusted and now also processes the predefined environment variables as well as the process environment variables.


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 20149: [DIP1000] Local data escapes inout method if not decorated with return
  16. Bugzilla 20163: Deprecated import in string mixin does not output diagnostic message
  17. Bugzilla 20164: Importing deprecated module at function-local scope does not output diagnostic message
  18. Bugzilla 20181: [nightly 2019-08-29] internal compiler error when static foreach iterating property method of struct
  19. Bugzilla 20223: C++, POSIX: Wrong mangling for const reference of callback
  20. Bugzilla 20224: Segfault when using ref parameter on a templated struct (C++ mangling)
  21. Bugzilla 20244: New dmd option -preview=noXlinker does not work on Linux to build a simple D application
  22. 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: std.zip: 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: std.zip 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 std.zip
  9. Bugzilla 20240: BitArray inconsistently preserves bits past length
  10. Bugzilla 20241: BitArray.bitsSet ignores length
  11. Bugzilla 20287: std.zip: 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 20219: Idle D programs keep consuming CPU in Gcx.scanBackground
  2. Bugzilla 20227: "Aborting from src/core/sync/event.d(141) Error: pthread_mutex_destroy failed." after fork()
  3. Bugzilla 20256: problem with signal handling and parallel GC on linux
  4. 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
  7. Bugzilla 20271: Handle forking in the GC

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 (45)

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

previous version: 2.088.0