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

previous version: 2.081.2 – next version: 2.082.1

Download D 2.082.0
released Sep 01, 2018

2.082.0 comes with 28 major changes and 76 fixed Bugzilla issues. A huge thanks goes to the 50 contributors who made 2.082.0 possible.

List of all bug fixes and enhancements in D 2.082.0.

Compiler changes

  1. Support for comparing arrays of unsigned byte-sized types and structs has been added to -betterC

    Prior to this release, the following code did not build in -betterC, but will with this release.

    // (Prior to this release) Error: TypeInfo cannot be used with -betterC
    struct Sint
        int x;
        this(int v) { x = v;}
    extern(C) void main()
        Sint[6] a1 = [Sint(1), Sint(2), Sint(3), Sint(1), Sint(2), Sint(3)];
        assert(a1[0..3] == a1[3..$]);
    // (Prior to this release) Linker Error: undefined reference to `core.internal.string.dstrcmp`
    extern(C) void main()
        auto s = "abc";
            case "abc":
    // (Prior to this release) Linker Error: undefined reference to `core.internal.string.dstrcmp`
    extern(C) void main()
        char[6] a = [1,2,3,1,2,3];
        assert(a[0..3] >= a[3..$]);  // failed for any byte-sized type (e.g. `char`, `ubyte`, etc...)
  2. Added D_ModuleInfo, D_Exceptions, and D_TypeInfo version identifiers

    D_ModuleInfo, D_Exceptions, and D_TypeInfo version identifiers were added to allow better precision in druntime and other library implementations.

    See Predefined Versions

  3. Deprecate conditional expression followed by an assign expression

    When a conditional expression is the left operand of an assign expression, they would be parsed as an assignment to the result of the conditional. This has now been deprecated. To preserve the existing behaviour, add parentheses for the conditional without including the assignment:

    bool test;
    int a, b, c;
    test ? a = b : c = 2;   // Deprecated
    (test ? a = b : c) = 2; // Equivalent

    This makes the intent clearer, because the first statement can easily be misread as the following code:

    test ? a = b : (c = 2);
  4. Unsafe code can now be used in debug blocks

    When writing debug code, one isn't interested in the type safety, but a pleasant debugging experience. The type checker already allowed to escape pure and @nogc within debug statement. With this release, @system code can be called from debug statements too:

    void main()
        int[] arr = [1, 2];
        debug unsafeCode(arr);
    @system void unsafeCode(T)(T[] arr)
        import core.stdc.stdio;
        printf("arr.ptr: %p", arr.ptr);
  5. Deprecate usage of opDot

    opDot was the D1 analog to alias this. However, alias this covers all use cases of opDot, but ensures safety.

    struct S
        int a, b;
    struct T
        S s;
        S* opDot()
            return &s;
    void main()
        T t;
        t.a = 4;
        assert(t.a == 4);
        t.b = 5;

    With alias this:

    struct S
        int a, b;
    struct T
        S s;
        alias s this;
    void main() @safe
        T t;
        t.a = 4;
        assert(t.a == 4);
        t.b = 5;
  6. D now supports deprecated, @disable and user-defined attributes on enum members


    template AliasSeq(TList...)
        alias AliasSeq = TList;
    enum MyEnum
        @("uda0") value0,
        @disable value1,
        deprecated value2  // Deprecation: enum member `main.MyEnum.value2` is deprecated
    static assert(__traits(getAttributes, MyEnum.value0) == AliasSeq!("uda0"));
    void main()
        auto v1 = MyEnum.value1;  // Error: enum member `main.MyEnum.value1` cannot be used because it is annotated with `@disable`
  7. Deprecated C-style array declarations will now result in a compilation error

    The deprecation period for C-style array declarations has expired. Beginning with this release, declaring arrays with C-style syntax will result in an error.

    int a[2];  // Error: instead of C-style syntax, use D-style `int a[2]`
    int[2] b;  // OK
  8. Mangling of extern(C++) template on Windows now correctly mangles const non-pointer template parameters.

    It used to ignore the const and was missing the $$C escape prefix.

    extern(C++) struct foo(T) {}
    extern(C++) void test(foo!(const(char)) a) {}
    // New
    static assert(test.mangleof == "?test@@YAXU?$foo@$$CBD@@@Z");
    // Old
    //static assert(test.mangleof == "?test@@YAXU?$foo@D@@@Z");
  9. .offsetof and .tupleof for fields of Objective-C classes have now been disabled

    To solve the fragile base class problem [1] in Objective-C, fields have a dynamic offset instead of a static offset. The compiler outputs a statically known offset which later the dynamic loader can update, if necessary, when the application is loaded. Due to this behavior it doesn't make sense to be able to get the offset of a field at compile time, because this offset might not actually be the same at runtime.

    To get the offset or value of a field, that is correct at runtime, functionality from the Objective-C runtime can be used instead [2].

    [1] Fragile Binary Interface Problem [2] Objective-C Runtime

  10. 64-bit OS X: Revert C++ mangling of long to pre-2.079 to restore size_t interop

    Direct interop of D size_t and C++ size_t was working before 2.079, on all platforms except for 32-bit OS X. By mangling D long as C++ long long on 64-bit OS X starting with 2.079, size_t interop broke on a more relevant platform. With new/fixed aliases, e.g., core.stdc.stdint.int64_t, core.stdc.stdint.uint64_t and core.stdc.config.cpp_size_t, there are now proper tools for portable C++ interop wrt. integers. Reverting to the previous C++ mangling on 64-bit OS X (C++ long) may save mixed D/C++ code bases from the need of manual adaptations by skipping the 2.079-2.081 DMD versions.

  11. UDAs on function parameters are now supported

    User-defined attributes on function parameters behave analogous to existing UDAs:

    void example(@(22) string param)
        @(11) string var;
        static assert([__traits(getAttributes, var)] == [11]);
        static assert([__traits(getAttributes, param)] == [22]);

Runtime changes

  1. Exception trapping can now be disabled via --DRT-trapExceptions=0

    Previously it was only possible to disable the trapping of exception by setting the global variable rt_trapExceptions to false. Now you can, for example, immediately open gdb at the uncaught exception:

    > gdb -ex run --args  --DRT-trapExceptions=0
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/usr/lib/".
    uncaught exception
    object.Exception@src/rt_trap_exceptions_drt.d(4): foo
    src/rt_trap_exceptions_drt.d:4 void rt_trap_exceptions_drt.test() [0x55591026]
    src/rt_trap_exceptions_drt.d:9 _Dmain [0x55591058]
    Program received signal SIGABRT, Aborted.
    0x00007ffff6e7b86b in raise () from /usr/lib/
    (gdb) bt full
    #0  0x00007ffff6e7b86b in raise () from /usr/lib/
    No symbol table info available.
    #1  0x00007ffff6e6640e in abort () from /usr/lib/
    No symbol table info available.
    #2  0x00005555555918cc in _d_throwdwarf (o=0x7ffff7ea4000) at src/rt/dwarfeh.d:233
            eh = 0x7ffff7fa4740
            refcount = 0
            r = 5
    #3  0x0000555555591027 in rt_trap_exceptions_drt.test() () at ../../src/object.d:2695
            innerLocal = 20
    #4  0x0000555555591059 in D main (args=...) at src/rt_trap_exceptions_drt.d:9
            myLocal = "bar"

    This Week in D for an in-depth explanation of rt_trapExceptions

  2. Additional functions for associative arrays

    The require function provides a means to construct a new value when the key is not present.

    class C{}
    C[string] aa;
    auto a = aa.require("a", new C);    // lookup "a", construct if not present

    The update function allows different operations to be performed depending on whether a value already exists or needs to be constructed.

    class C{}
    C[string] aa;
    C older;
    C newer;
        newer = new C;
        return newer;
    (ref C c)
        older = c;
        newer = new C;
        return newer;

    The functions avoid the need to perform multiple key lookups. Further details are available in the spec.

  3. TypeInfo.getHash now uses core.internal.hash.hashOf functions for hash computing

    Now typeid(typeof(var)).getHash(&var) should be always equal hashOf(val). hashOf uses MurmurHash3 algorithm for bitwise hashing, including string hashing. Old implementation used polynomial hash for string hashing, which often provided lexicographical order of strings in associative array. However AA doesn't guarantee some specific order of elements, thus tests which rely on it should be changed.

  4. core.sys.posix.utsname.update renamed to version_

    The struct that uname returns - utsname - has the field version in C. The D definition of the struct cannot match that, because version is a keyword in D. So, it's been called update, which is not an obvious choice. It is more in line with current naming policies (and more in line with the name in C) for it to be called version_, since that's the closest that we can get to version in D. So, update has now been renamed to version_, and update is an alias of version_ which will be deprecated in a future release.

Library changes

  1. Single- and double-precision implementations for (a)tan and exp function families

    The float and double overloads of std.math.atan, std.math.atan2, std.math.tan, std.math.exp, std.math.expm1 and std.math.exp2 previously forwarded to the real implementation (inline assembly) and now got proper 'software' implementations in the corresponding precision.

    While this may result in a slowdown in some cases for DMD (especially for exp() and exp2()), the overall speed-up factor for LDC is > 3, for both double and float.

    This also implies less precise results, especially in single-precision, so if your code depended on more accurate results via 80-bit intermediate precision, you'll have to cast the argument(s) explicitly now.

  2. std.algorithm.iteration.each is now capable of early-stopping

    std.algorithm.iteration.each is now capable of exiting early. When a No.each std.typecons.Flag is returned from the function that is called by each, the iteration will be aborted early. Analogously, returning Yes.each will continue the iteration. For example:

    auto arr = [10, 20, 30];
    arr.each!((n) { arr ~= n; return (n == 20) ? No.each : Yes.each; }); // aborts after the second iteration
    assert(arr == [10, 20, 30, 10, 20]);
  3. std.algorithm.iteration.joiner can now be used for bidirectional ranges

    std.algorithm.iteration.joiner can now be requested to be a bidirectional range.

    import std.algorithm.iteration : joiner;
    import std.range : retro;
    [[1, 2], [3, 4]].joiner.retro; // [4, 3, 2, 1]

    A more complex example of inserting a format delimiter fully lazily:

    import std.algorithm.comparison : equal;
    import std.range : chain, cycle, iota, only, retro, take, zip;
    import std.format : format;
    static immutable number = "12345678";
    static immutable delimiter = ",";
    auto formatted = number.retro
        .map!(z => chain(z[0].only, z[1] == 2 ? delimiter : null))
        .retro; // "12,345,678"
  4. std.algorithm.searching.skipOver can now handle variadic arguments

    std.algorithm.skipOver which allows to move over a needle if it matches now accepts variadic arguments for needles to skip over:

    auto s = "";
    assert(!s.skipOver("dlang", "DLF", "DLang "));
    assert(s == "");
    assert(s.skipOver("dlang", "DLANG", "DLF", "D", "DL", "DLanp"));
    assert(s == "");
  5. Added staticArray to construct a static array from array / input range. Includes a length-inferring compile-time variant.

    The type of elements can be specified implicitly so that [1, 2].staticArray results in int[2], or explicitly, e.g. [1, 2].staticArray!float returns float[2]. When a is a range whose length is not known at compile time, the number of elements must be given as template argument (e.g. myrange.staticArray!2). Size and type can be combined, if the source range elements are implicitly convertible to the requested element type (eg: 2.iota.staticArray!(long[2])). When the range a is known at compile time, it can also be specified as a template argument to avoid having to specify the number of elements (e.g.: staticArray!(2.iota) or staticArray!(double, 2.iota)).

    import std.range : iota;
    auto input = 3.iota;
    auto a = input.staticArray!2;
    static assert(is(typeof(a) == int[2]));
    assert(a == [0, 1]);
    auto b = input.staticArray!(long[4]);
    static assert(is(typeof(b) == long[4]));
    assert(b == [0, 1, 2, 0]);
  6. Deprecated functions for getting the timezone have been removed.

    Due to the fact that Microsoft changes its timezone definitions too frequently to maintain the conversion between the IANA TZ Database names and the names that Microsoft uses in the standard library, several functions in std.datetime.timezone related to getting the time zone independently of the host OS were previously deprecated: TimeZone.getTimeZone, TimeZone.getInstalledTZNames, tzDatabaseNameToWindowsTZName, and windowsTZNameToTZDatabaseName. These functions have now been fully removed.

    Instead of TimeZone.getTimeZone, std.datetime.timezone.PosixTimeZone.getTimeZone and std.datetime.timezone.WindowsTimeZone.getTimeZone should be used directly. Instead of Timezone.getInstalledTimeZones, std.datetime.timezone.PosixTimeZone.getInstalledTZNames and std.datetime.timezone.WindowsTimeZone.getInstalledTZNames should be used directly. And any programs looking to convert between the TZ Database names and the Windows names can use std.datetime.timezone.parseTZConversions with the current windowsZones.xml file to get the current conversions (see the documenation for std.datetime.timezone.parseTZConversions for details).

Installer changes

  1. Windows installer and binaries are now code-signed

    All released executables on Windows will now be code-signed by the following certificate.

        Issuer: C = US, O = DigiCert Inc, OU =, CN = DigiCert SHA2 Assured ID Code Signing CA
        Serial Number: 04:e7:49:06:78:3a:e6:5f:54:37:fd:55:45:66:5f:e5
            Not Before: Aug  7 00:00:00 2018 GMT
            Not After : Aug 11 12:00:00 2021 GMT
        Subject: C = US, ST = Washington, L = Kirkland, O = D Language Foundation, CN = D Language Foundation
        SHA1 Fingerprint: BD:E0:0F:CA:EF:6A:FA:37:15:DB:D4:AA:1A:43:2E:78:27:54:E6:60
        SHA256 Fingerprint: AA:B0:6F:7B:A8:26:52:51:C4:24:44:1B:34:8E:30:68:F4:34:DB:35:38:6A:17:A7:45:C3:27:77:11:24:C4:E5

    Nightly builds and branch/feature previews will not be code-signed for now.

Dub changes

  1. Variables such as $ARCH or $PLATFORM are now supported in the build settings.

    JSON lines such as

        "lflags-posix-x86": [ "-L$PACKAGE_DIR/lib/posix-x86" ],
        "lflags-posix-x86_64": [ "-L$PACKAGE_DIR/lib/posix-x86_64" ],

    can be turned into

        "lflags-posix": [ "-L$PACKAGE_DIR/lib/posix-$ARCH" ],

    Both $VAR and ${VAR} syntaxes are supported. The supported variables are as follow:

    name values
    $ARCH "x86", "x86_64"
    $PLATFORM "linux", "windows", ...
    $PLATFORM_POSIX "posix", "windows", ...
    $BUILD_TYPE "debug", "release", ...

  2. DUB supports build type "syntax"

    With this release new build type "syntax" is added. This build type is useful for IDEs to check the syntax of D coding without generating binaries.

  3. Enviroment variable expansion was improved

    Environment variable expansion now supports the braced ${MY_VAR} expansion syntax: e.g. for ${PACKAGE_PATH}_suffix.

    Moreover, $PACKAGE_PATH, $ROOT_PACKAGE_PATH, and $DEP_PACKAGE_PATH no longer end with a / or \ to support clean concatenation, e.g. ${PACKAGE_PATH}/subpath.

    Learn more about the details at #1392.

  4. Dependency resolution has been reimplemented using a recursive algorithm

    The new algorithm minimizes the search space while descending the dependency graph. Compared to the old approach, it is now much less likely to run into pathological cases that result in exponential run time ("The dependency resolution algorithm is taking too long").

    Furthermore, the error message in case of unsatisfiable dependencies is more precise, usually making it straight forward to debug issues in the dependency graph of a failing package.

  5. DUB accepts single file packages on STDIN

    You can pass single file packages to dub on STDIN using dash as first argument to DUB. All arguments after dash will be passed as runtime arguments to the application.

    Example cat app.d | dub - --foo=bar

  6. The regular upgrade check has been removed

    Previously dub would regularly (once a day) check for possible package upgrades before building a packages. This lead to unexpected build failures, e.g. when internet connectivity was down or dependency resolution failed, and caused unnecessary delays.

    The build flag --nodeps now only suppresses resolution of missing dependencies.

    The new upgrade flag --dry-run was added to explicitly check for upgradable packages without actually upgrading anything.

List of all bug fixes and enhancements in D 2.082.0:

DMD Compiler regressions

  1. Bugzilla 18068: No file names and line numbers in stack trace
  2. Bugzilla 19050: Running the DMD test suite with a compiler compiled in debug mode fails due to invalid characters, -
  3. Bugzilla 19058: __traits(getUnitTests) stops working with separate compilation in dmd 2.081.0
  4. Bugzilla 19074: [REG 2.080] SIGSEGV in el_ptr (s=0x15) at dmd/backend/el.c:1760
  5. Bugzilla 19076: dmd 2.081 crashed by getVirtualFunctions for a interface extended interface
  6. Bugzilla 19134: [C++] static const y = new Derived(); ->pointer cast from const(Derived) to immutable(void*)** is not supported at compile time
  7. Bugzilla 19140: [REG master] AssertError@dmd/ctfeexpr.d(229): Assertion failure
  8. Bugzilla 19152: 2.081.1 getOverloads regression compiler bug
  9. Bugzilla 19162: [REG: 2.079.0] Public Import Overlapping Names Conflict Resolution

DMD Compiler bugs

  1. Bugzilla 9701: UDAs cannot be attached to enum values.
  2. Bugzilla 15373: Segfault when using typeid on extern(C++) class with virtual functions
  3. Bugzilla 17580: Marking methods as synchronized is allowed despite spec
  4. Bugzilla 18620: error cannot be interpreted at compile time is missing context where error occurs
  5. Bugzilla 18985: bad error message for += operation on shared Object
  6. Bugzilla 19018: Lexer allows invalid integer literals, like 0x
  7. Bugzilla 19035: Escape in scope inference, improve scope inference
  8. Bugzilla 19043: Incorrect mangling for extern(C++) const template parameter on windows
  9. Bugzilla 19051: Undefined functions Set/GetWindowLongPtr in mingw libs
  10. Bugzilla 19053: debug should escape @safe
  11. Bugzilla 19059: Invalid integer literal 08 and 09 allowed
  12. Bugzilla 19107: -de produces compilation error, -dw does not
  13. Bugzilla 19112: Associative array opIn with static array key fails with dynamic array
  14. Bugzilla 19176: Dmd crashes because of __traits(getUnitTests)
  15. Bugzilla 19181: Semantic errors in opDispatch argument lead to "no property X"
  16. Bugzilla 19187: __traits(compiles) segfaults on access to partially undefined overload set from import
  17. Bugzilla 19193: deprecated attribute on enum members in templates is ignored

DMD Compiler enhancements

  1. Bugzilla 17602: improve message for deprecated enum comparison
  2. Bugzilla 18743: ConditionalExpression and AssignExpression should require parentheses
  3. Bugzilla 18994: Use noncopyable variable in foreach loop without ref results in error message without line number
  4. Bugzilla 19022: CTorFlow: Show the line of the duplicated initialization for const/immutable fields
  5. Bugzilla 19081: Can't declare enum with UDA at statement level
  6. Bugzilla 19108: Unknown pragmas not ignored inside body

Phobos bugs

  1. Bugzilla 12507: SysTime.init.toString should not segfault
  2. Bugzilla 15732: std.function partial does not work with function / delegate references
  3. Bugzilla 18682: std.typecons.Nullable has opEquals but no toHash
  4. Bugzilla 18804: std.algorithm.mutation.copy puts whole source range into target range when it should put elements
  5. Bugzilla 18933: std.range.assumeSorted should not nest SortedRange!(SortedRange!(...), pred)
  6. Bugzilla 18995: std.array.array doesn't free elements
  7. Bugzilla 19003: format!"" breaks with structs containing invariants violated in .init
  8. Bugzilla 19094: Anchored section does not exist in std.uni.normalize phobos documentation
  9. Bugzilla 19138: std.uuid.randomUUID should not depend on std.random.Random being Mt19937
  10. Bugzilla 19147: Reduce template bloat in std.complex by using const arguments
  11. Bugzilla 19171: Array!bool range slicing has invalid assert

Phobos enhancements

  1. Bugzilla 12335: std.algorithm.skipOver should support multiple args like startsWith
  2. Bugzilla 13121: std.algorithm.joiner should return a bidirectional range if possible
  3. Bugzilla 14001: Optionally @nogc std.random.randomCover
  4. Bugzilla 16639: Review std.json wrt this article on JSON edge cases and ambiguities
  5. Bugzilla 16745: Add template helper for creating static arrays with the size inferred
  6. Bugzilla 17019: std.algorithm.iteration.each should be usable with parallel
  7. Bugzilla 18790: can't put a const(char)[] into a char[]
  8. Bugzilla 19037: Nullable should use moveEmplace to support any type.
  9. Bugzilla 19135: std.json : JSON_TYPE does not match D Style.
  10. Bugzilla 19156: @nogc std.random.randomShuffle

Druntime bugs

  1. Bugzilla 19046: OSX: bad value for core.stdc.time.CLOCKS_PER_SEC
  2. Bugzilla 19073: core.internal.hash should not bitwise hash representations of floating point numbers
  3. Bugzilla 19177: No version (Solaris) in druntime/src/core/stdc/time.d

Druntime enhancements

  1. Bugzilla 18220: Allow rt_trapexceptions to be set from the CLI
  2. Bugzilla 18918: core.internal.hash should perform memberwise hashing of structs with references
  3. Bugzilla 18921: make core.internal.hash cater to memberwise hash chaining
  4. Bugzilla 18923: Semaphore internal handle should be protected instead of private
  5. Bugzilla 18942: core.internal.hash can take advantage of alignment info on non-x86
  6. Bugzilla 18981: SIGSEGV during backtrace when debug info is compressed
  7. Bugzilla 19009: core.internal.hash.hashOf default hash (absent toHash) should be @nogc
  8. Bugzilla 19048: In core.internal.hash.hashOf reduce template bloat: remove auto ref where unneeded and add const where possible
  9. Bugzilla 19049: object.hashOf - don't wrap a public function with an identical public function
  10. Bugzilla 19071: core.internal.hash should have non-chained toHash overloads
  11. Bugzilla 19072: Object.toHash and typeid(void*).getHash(&ptr) should be more varied in their low bits
  12. Bugzilla 19075: rt.util.random.Rand48.defaultSeed should prefer RDTSC or mach_absolute_time or QueryPerformanceCounter to ctime.time bugs

  1. Bugzilla 18558: Template alias spec incomplete
  2. Bugzilla 18782: Documentation error: ProtectionAttributes should say Visibility Attributes
  3. Bugzilla 19055: [404 Not Found] std.digest.digest
  4. Bugzilla 19067: [Mixins] Dead Link to template-mixin enhancements

  1. Bugzilla 19041: errnoEnforce: example does not compile

Installer bugs

  1. Bugzilla 2473: Linux system install instructions incorrect
  2. Bugzilla 10941: object.d not found when following Mac installation instructions
  3. Bugzilla 19100: signature verification fails, no public key

Contributors to this release (50)

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

previous version: 2.081.2 – next version: 2.082.1