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

previous version: 2.082.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.083.0 comes with 22 major changes and 52 fixed Bugzilla issues. A huge thanks goes to the 53 contributors who made 2.083.0 possible.

List of all upcoming bug fixes and enhancements in D 2.083.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";
        switch(s)
        {
            case "abc":
                break;
            default:
                break;
        }
    }
    
    // (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

    Example

    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] https://en.wikipedia.org/wiki/Fragile_binary_interface_problem [2] https://developer.apple.com/documentation/objectivec/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/libthread_db.so.1".
    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/libc.so.6
    (gdb) bt full
    #0  0x00007ffff6e7b86b in raise () from /usr/lib/libc.so.6
    No symbol table info available.
    #1  0x00007ffff6e6640e in abort () from /usr/lib/libc.so.6
    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;
    aa.update("a",
    {
        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
        .zip(3.iota.cycle.take(number.length))
        .map!(z => chain(z[0].only, z[1] == 2 ? delimiter : null))
        .joiner
        .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 = "DLang.rocks";
    assert(!s.skipOver("dlang", "DLF", "DLang "));
    assert(s == "DLang.rocks");
    
    assert(s.skipOver("dlang", "DLANG", "DLF", "D", "DL", "DLanp"));
    assert(s == "ang.rocks");
    
  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 = www.digicert.com, 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
        Validity
            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.


List of all bug fixes and enhancements in D 2.083.0:

DMD Compiler regressions

  1. Bugzilla 19219: Could not CTFE with std.math.exp from 2.082.0
  2. Bugzilla 19243: [REG 2.081] Can no longer override pragma(lib) with -L switch
  3. Bugzilla 19248: Wrong mangle for C++ const STL classes/structs
  4. Bugzilla 19266: Some source files names are no longer accepted
  5. Bugzilla 19304: [Reg 2.081.0] Linker arguments order changed in issue 15574 hinders using --whole-archive linker directive

DMD Compiler bugs

  1. Bugzilla 11538: [ICE] stack overflow with recursive NullableRef fails
  2. Bugzilla 14246: RAII - proper destruction of partially constructed objects/structs
  3. Bugzilla 15374: [internal] Nothing should import ddmd.mars
  4. Bugzilla 18457: betterC - struct destructor is always called at function return
  5. Bugzilla 18771: Identical overload sets in different modules have different identities
  6. Bugzilla 18955: extern(C++) default struct mangling is overridden when interacting with a cppmangle = class template
  7. Bugzilla 19098: Improve error for non-assignable struct
  8. Bugzilla 19181: Semantic errors in opDispatch argument lead to "no property X"
  9. Bugzilla 19182: missing semicolon crashes compiler
  10. Bugzilla 19185: [ICE] Nested struct segfaults when using variable from outer scope
  11. Bugzilla 19209: [ICE] Overriding a field in a baseclass issues an ICE
  12. Bugzilla 19225: Confusing error message on static else
  13. Bugzilla 19251: Alias this does not get called on struct qualified type
  14. Bugzilla 19284: alias this not used in nested functions of a method

DMD Compiler enhancements

  1. Bugzilla 15512: extern(C++, ns) should consider taking a string
  2. Bugzilla 19180: Expose dmd.mtype.Type.isZeroInit as __traits(isZeroInit, T)
  3. Bugzilla 19194: version for -mscrtlib specification
  4. Bugzilla 19195: Support pragma to specify linker directives
  5. Bugzilla 19199: Use core.bitops intrinsics during CTFE
  6. Bugzilla 19203: alias this to a bool behaves both inconsistently and incorrectly with static assert
  7. Bugzilla 19212: Add versions for C++ runtimes.
  8. Bugzilla 19292: Mixin expressions should take an argument list the same as pragma(msg) does

Phobos regressions

  1. Bugzilla 19252: Templated format with variable width allocates 2GB of RAM per call.

Phobos bugs

  1. Bugzilla 11431: std.file.slurp fails with Windows newlines
  2. Bugzilla 11959: Phobos should not declare public symbols in version(unittest) blocks
  3. Bugzilla 17276: BaseClassesTuple fails on extern C++ classes that implement an interface without a base class
  4. Bugzilla 18675: std.experimental.checkedint.Checked has opEquals but no toHash
  5. Bugzilla 18683: std.containers.rbtree.RedBlackTree has opEquals but no toHash
  6. Bugzilla 18838: Formatting the number zero with separator doesn't obey width specifier
  7. Bugzilla 18851: std.net.curl.post cannot be used with !ubyte
  8. Bugzilla 19085: std.experimental.allocator.makeArray should work with void
  9. Bugzilla 19200: Variant operators don't overload correctly
  10. Bugzilla 19207: std.algorithm.subsitute wrong results for single subrange substitution
  11. Bugzilla 19228: hasAliasing fails on static arrays
  12. Bugzilla 19240: std.typecons.Tuple should check for reserved identifiers
  13. Bugzilla 19275: std.process: redirecting output in a non-console application fails
  14. Bugzilla 19289: std.range.transposed with enforceNotJagged not throwing
  15. Bugzilla 19297: JSONValue of signed and unsigned equal values is not equal

Phobos enhancements

  1. Bugzilla 18142: checkedint opOpAssign doesn't accept a checkedint
  2. Bugzilla 19236: Replace runtime typeid(T).initializer().ptr is null checks with compile-time __traits(isZeroInit, T)
  3. Bugzilla 19257: std.array.join does not handle const fields that cannot be converted to mutable

Druntime bugs

  1. Bugzilla 19250: DWARF Backtraces with very long symbol names read out of bounds when printing
  2. Bugzilla 19262: hashOf associative array should infer nothrow
  3. Bugzilla 19282: hashOf segfaults for non-null C++ objects
  4. Bugzilla 19314: Thread object destruction may result in UB

Druntime enhancements

  1. Bugzilla 19280: Remove unnecessary error checks in core.time.currSystemTick and currTime

dlang.org bugs

  1. Bugzilla 18104: Alias example compiles where it states that it should be illegal

Contributors to this release (53)

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

previous version: 2.082.0