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

previous version: 2.080.1 – next version: 2.081.1

Download D 2.081.0
released Jul 01, 2018

List of all bug fixes and enhancements in D 2.081.0.

Compiler changes

  1. Deprecate allowing a constructor declaration in a static block

    Before patch: 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 samples do not affect the constructor in any way:

        this() {}
        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
            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.

    After patch: Whenever a constructor is encountered in a static context a deprecation message is issued 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()).

  2. Deprecate usage of this and super as types

    Prior to this release, this and super could be used as both data or types depending on the context. Starting with this release using this or super as a type will result in a compiler error.

    class C
        shared(this) x;    // Deprecation: Using `this` as a type is deprecated. Use `typeof(this)` instead
    class D : C
        shared(super) a;   // Deprecation: Using `super` as a type is deprecated. Use `typeof(super)` instead
        super b;           // Deprecation: Using `super` as a type is deprecated. Use `typeof(super)` instead

    Use typeof(super) or typeof(this) instead.

    class C
        shared(typeof(this)) x;
    class D : C
        shared(typeof(super)) a;
        typeof(super) b;
  3. Implement DIP 1009 - Add Expression-Based Contract Syntax

    Expression-based contract syntax has been added: Contracts that consist of a single assertion can now be written more succinctly and multiple in or out contracts can be specified for the same function.


    class C {
        private int x;
        invariant(x >= 0);
        // ...
    int fun(ref int a, int b)
        in(a > 0)
        in(b >= 0, "b cannot be negative")
        out(r; r > 0, "return must be positive")
        out(; a != 0)
        // ...
  4. extern (C++) construction, destruction, operators and other mangling improvements

    Many improvements have been made to the extern(C++) experience in this release cycle.

    Mangling improvements include:

    • Constructor/destructor mangling matches C++
    • Compatible D style operators now mangle as C++ operators
    • nullptr_t mangles correctly
    • Various mangling bugs have been fixed

    extern(C++) APIs that use nullptr_t can use typeof(null) on the D side:

    alias nullptr_t = typeof(null);
    extern (C++) void fun(nullptr_t);

    extern (C++) mangling of operators is working for all operators that are semantically equivalent. This list includes all instantiations of opUnary, opBinary, opAssign, opOpAssign, opCast, opEquals, opIndex, opCall. Two notable exceptions are opCmp, and C++ operator !, which don't have compatible implementations.

    Mangling of extern (C++) class constructors and destructor are working.

    This release also includes ABI fixes where destructors are now correctly added to the virtual table, and constructor/destructor calling semantics now match C++. With this, mixed-language class hierarchies are working, with construction/destruction being supported in either language.

  5. Support for iterating template overloads

    __traits(getOverloads) has been extended to return template overloads when passed an optional parameter with a true value.

    struct S
        static int foo()() { return 0; }
        static int foo()(int n) { return 1; }
        static int foo(string s) { return 2; }
        enum foo(int[] arr) = arr.length;
    alias AliasSeq(T...) = T;
    alias allFoos = AliasSeq!(__traits(getOverloads, S, "foo", true));
    static assert(allFoos.length == 4);
    static assert(allFoos[0]("") == 2);
    static assert(allFoos[1]() == 0);
    static assert(allFoos[2](1) == 1);
    alias foo3 = allFoos[3];
    static assert(foo3!([]) == 0);
  6. __traits(getLinkage, ...) now works on structs, classes, and interfaces.

    It is now possible to detect the language ABI specified for a struct, class, or interface.

    class MyClass {}
    extern (C++) struct MyCPPStruct {}
    extern (C++) interface MyCPPInterface {}
    extern (Objective-C) interface MyObjcInterface {}
    static assert(__traits(getLinkage, MyClass) == "D");
    static assert(__traits(getLinkage, MyCPPStruct) == "C++");
    static assert(__traits(getLinkage, MyCPPInterface) == "C++");
    static assert(__traits(getLinkage, MyObjcInterface) == "Objective-C");
  7. Implicit catch statements will now result in an error

    See the Deprecated Features for more information.

    Implicit catch statements were deprecated in 2.072. Starting with this release, implicit catch statements will cause the compiler to emit an error.

    import std.stdio;
    void main()
        int[] arr = new int[](10);
        // This will throw a RangeError
        try { arr[42]++; }
        catch  // Error: `catch` statement without an exception specification is deprecated;
               // use `catch(Throwable)` for old behavior
            writeln("An error was caught and ignored");
  8. Implicit comparison of different enums will now result in an error

    See the Deprecated Features for more information.

    Implicit comparison of different enums was deprecated in 2.075. Starting with this release, implicit comparison of different enums will cause the compiler to emit an error.

    enum Status
    enum OtherStatus
    static assert(Status.good == OtherStatus.ok); // Error: Comparison between different enumeration types `Status` and `OtherStatus`;
                                                  // If this behavior is intended consider using `std.conv.asOriginalType`
  9. Implicit string concatenation will now result in an error

    See the Deprecated Features for more information.

    Implicit string concatenation was deprecated in 2.072. Starting with this release, implicit string concatenation will cause the compiler to emit an error.

    void main()
        string s = "Hello" ", World!";  // Error: Implicit string concatenation is deprecated, use "" ~ "" instead
  10. IRETQ is now supported in inline assembler.

    IRETQ is the 64-bit version of the already supported IRET instruction. With its inclusion, it is now possible to write 64-bit interrupt service routines in pure D.

    void isr()
            // ...
  11. Interfaces and classes can be used without the runtime if only static fields are utilized

    Prior to this release any attempt to use interfaces and/or classes without the runtime would result in compile-time errors due to the lack of TypeInfo. However, as long as classes are not instantiated there is no need for TypeInfo.

    Beginning with this release the compiler will no longer emit errors about missing TypeInfo when using interfaces and/or classes as long as they are not instantiated and only shared static members are utilized.

    Example 1

    module object
    private alias extern(C) int function(char[][] args) MainFunc;
    private extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc)
        return mainFunc(null);  // assumes `void main()` for simplicity
    interface I
        shared static int i;
    class A : I
        shared static int a;
    class B : A
        shared static int b;
    void main()
        B.b = B.a + B.i;

    dmd -conf= -defaultlib= main.d object.d -of=main
    size main
       text    data     bss     dec     hex filename
       1867    1208      32    3107     c23 main

    Non-shared static members can also be used, but will require a thread-local storage (TLS) implementation. For example, on Linux the TLS implementation is already supplied by the C runtime and C standard library, so, since dmd automatically calls gcc to link the final executable, it will automatically bring in the TLS implementation.

    Example 2

    module object
    private alias extern(C) int function(char[][] args) MainFunc;
    private extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc)
        return mainFunc(null);  // assumes `void main()` for simplicity
    interface I
        static int i;
    class A : I
        static int a;
    class B : A
        static int b;
    void main()
        B.b = B.a + B.i;

    dmd -conf= -defaultlib= main.d object.d -of=main
    size main
       text    data     bss     dec     hex filename
       2123    1296      28    3447     d77 main

    Some platforms may require some TLS implementation code or some specialized build procedures to link in a TLS implementation.

    This will hopefully reduce friction for those using D without the runtime, porting D to new platforms, or using D from other langauges, while enabling more features and idioms of D to be used in those use cases.

  12. Specifying redundant storage classes will now result in a compiler error

    Specifying redundant storage classes was deprecated long ago and was originally scheduled to emit a compiler error beginning with the 2.068 release. That promise has been fulfilled with this release.

    @safe void f() @safe {}   // Error: redundant attribute `@safe`

Runtime changes

  1. Filenames and line numbers have been added to stacktraces on macOS

    When an exception is throw and not caught, a stacktrace is printed. On Linux, FreeBSD and DragonFlyBSD this stacktrace includes the filenames and line numbers, if the application was built with debug info enabled. This feature has now been added to macOS.

    This requires support from the compiler since debug info is stripped by the linker on macOS.


    void bar()
        throw new Exception("bar");
    void foo()
    void main()

    Compiling the above code, with debug info enabled, by running: dmd -g main.d. When running the application it will produce an output similar to:

    object.Exception@main.d(3): bar
    main.d:3 void [0x71afdfb]
    main.d:8 void [0x71afe0c]
    main.d:13 _Dmain [0x71afd78]

  2. object.destroy() supports extern(C++) classes.

    object.destroy() was crashing when called with an extern(C++) class. It now correctly destructs and resets the object to init.

  3. Add missing declarations to core.sys.darwin.mach.getsect

    Declarations that were missing from mach-o/getsect.h has been added to core.sys.darwin.mach.getsect.

Library changes

  1. The deprecated std.c package has been removed.

    Use the core.stdc package instead.

  2. The performance of std.algorithm.iteration.joiner has been improved


    > dmd -O -inline -release ./joiner.d && ./joiner
    before.joiner   = 57 secs, 834 ms, 289 μs, and 3 hnsecs
    new.joiner      = 44 secs, 936 ms, 706 μs, and 5 hnsecs


    > ldmd -O3 -release -inline joiner.d && ./joiner
    before.joiner   = 5 secs, 180 ms, 193 μs, and 7 hnsecs
    new.joiner      = 3 secs, 168 ms, 560 μs, and 6 hnsecs

    The benchmark code can be found here.

  3. std.algorithm.mutation.remove now only accepts integral values or pair of integral values as offset

    Previously, without being stated in the documentation, std.algorithm.remove used to accept any values as offset. This behavior was very error-prone:

    import std.algorithm, std.stdio;
    [0, 1, 2, 3, 4].remove(1, 3).writeln; // 0, 2, 4  -- correct
    [0, 1, 2, 3, 4].remove([1, 3]).writeln; // 0, 3, 4  -- incorrect

    With this release, using arrays as individual elements is no longer valid. std.typecons.tuple can be used to explicitly indicate that a range from start to stop (non-enclosing) should be removed:

    import std.algorithm, std.stdio, std.typecons;
    [0, 1, 2, 3, 4].remove(tuple(1, 3)).writeln; // 0, 3, 4

    However, only 2-tuples are allowed to avoid this un-intuitive scenario:

    import std.algorithm, std.stdio, std.typecons;
    [0, 1, 2, 3, 4].remove(tuple(1, 3, 4)).writeln; // 0, 4?
  4. Changed semantics of std.math.{fmin,fmax} wrt. NaNs.

    The semantics of std.math.fmin and std.math.fmax have been streamlined with the C functions: if one of the arguments is a NaN, return the other. This involves an additional std.math.isNaN check. Use std.algorithm.comparison.min and std.algorithm.comparison.max for the previous semantics performing a single comparison.

    import std.math;
    assert(fmin(real.nan, 2.0L) == 2.0L);
    assert(fmin(2.0L, real.nan) == 2.0L); // previously: NaN
    assert(isNaN(fmin(real.nan, real.nan)));
    import std.algorithm.comparison;
    assert(min(real.nan, 2.0L) == 2.0L);
    assert(isNaN(min(2.0L, real.nan)));
    assert(isNaN(min(real.nan, real.nan)));

Dub changes

  1. DUB supports "customCachePaths" for providing read-only package paths

    With this release DUB allows defining additional paths that contain packages in subfolders with the pattern "(name)-(version)/(name)/" by defining a "customCachePaths" field in /etc/dub/settings.json or ~/.dub/settings.json.

    "customCachePaths" can be used to provide prebuilt DUB libraries (e.g. for distribution package maintainers).

List of all bug fixes and enhancements in D 2.081.0:

DMD Compiler regressions

  1. Bugzilla 18068: No file names and line numbers in stack trace
  2. Bugzilla 18821: DMD segfault when doing unsafe operation outside of any function
  3. Bugzilla 18905: [Reg 2.079] C++ classes can no longer be used with -betterC
  4. Bugzilla 18936: Internal error: dmd/backend/cgxmm.c 684
  5. Bugzilla 19024: [REG 2.081-beta] AssertError@dmd/dsymbolsem.d(4317): Assertion failure

DMD Compiler bugs

  1. Bugzilla 5153: Struct pointer to struct variable assign error message
  2. Bugzilla 7443: Better diagnostic on wrongly written static constructor
  3. Bugzilla 11742: cannot inizialize void initialized static variable in static constructor.
  4. Bugzilla 12764: Disabled struct default construction circumvented when field is written to
  5. Bugzilla 12807: UFCS checks "alias this" attributes even when not called
  6. Bugzilla 13435: Strange error if struct is a class member and opAssign applied
  7. Bugzilla 13741: std.traits.moduleName & packageName do not work with functions that have parameters
  8. Bugzilla 14178: C++ linux name mangling does not handle standard abbreviations for const types
  9. Bugzilla 14739: Immutable alias to template triggers dmd assert
  10. Bugzilla 15068: wrong error message on attempting to use type as template
  11. Bugzilla 15388: extern(C++) - typeof(null) should mangle as nullptr_t
  12. Bugzilla 15475: Ddoc code sample with unbalanced paren comes out as macro
  13. Bugzilla 15574: wrong order of linker arguments
  14. Bugzilla 15755: DMD segfault upon alias on alias on __trait(getAttributes, ...)
  15. Bugzilla 15869: RVO can overwrite argument
  16. Bugzilla 16088: Parse error for import expression in statement
  17. Bugzilla 16206: traits getOverloads fails when one of the overload is a templatized function
  18. Bugzilla 17373: traits getOverloads + multiple interface inheritance only see one of the interfaces' overloads
  19. Bugzilla 18228: this(this a){} doesn't generate postblit ctor; this(this){} does
  20. Bugzilla 18236: Invalid line reported on error casting enum
  21. Bugzilla 18266: ICE: should allow reusing identifier in declarations in disjoint scopes in a function
  22. Bugzilla 18365: header file generation doesn't include the return attribute
  23. Bugzilla 18584: Undefined identifier when not specifying 'this'
  24. Bugzilla 18730: dmd miscompiles with -O
  25. Bugzilla 18746: function returning empty struct isn't called if used in equality expression
  26. Bugzilla 18775: DMD falsely reports deprecation for deprecated implicit casts that were not used in UFCS
  27. Bugzilla 18803: just "static if" in nested import crashes dmd
  28. Bugzilla 18828: [-betterC] helpless error in object.d
  29. Bugzilla 18858: switch 'skips declaration' test only checks last declaration
  30. Bugzilla 18868: Separate compilation generates two static this functions, runs it twice
  31. Bugzilla 18888: extern(C++) template arg/alias arg mangling issue
  32. Bugzilla 18890: extern(C++) mangles all destructors the same
  33. Bugzilla 18891: extern(C++) destructor prototype should just link; not generate field/aggregate dtor
  34. Bugzilla 18892: Wrong type in error message for static members and alias this
  35. Bugzilla 18916: ICE using Typedef and __LINE__
  36. Bugzilla 18922: dmd doesn't do substitutions for C++ namespaces in different module/file
  37. Bugzilla 18928: extern(C++) bad codegen, wrong calling convention
  38. Bugzilla 18951: package static method masked by public static method in class
  39. Bugzilla 18953: Win32: extern(C++) struct destructor not called correctly through runtime
  40. Bugzilla 18957: extern(C++) doesn't mangle 'std' correctly on posix systems
  41. Bugzilla 18966: extern(C++) constructor should match C++ semantics assigning vtable
  42. Bugzilla 18970: DMD segfault due to opDispatch
  43. Bugzilla 18976: Inconsistency in overload merging with aliases
  44. Bugzilla 18984: Debugging stack struct's which are returned causes incorrect debuginfo.

DMD Compiler enhancements

  1. Bugzilla 14086: Invalid extern C++ name for constructor / destructor
  2. Bugzilla 15589: extern(C++) virtual destructors are not put in vtbl[]
  3. Bugzilla 15691: Improve error message for struct member initializer
  4. Bugzilla 18859: Silence class allocator/deallocator deprecation warning if they are marked "deprecated"
  5. Bugzilla 18963: Relax restrictions on 'return' parameters when parameter is not a pointer

Phobos regressions

  1. Bugzilla 18937: [REG 2.080.0] std.experimental.allocator: compiling make needs an unreasonable amount of memory for structs that contain static arrays
  2. Bugzilla 18993: toLower is broken for UTF chars

Phobos bugs

  1. Bugzilla 12086: std.algorithm.remove + range of indices produces wrong results
  2. Bugzilla 17084: Can't sort array of structs with alias this: swap can't call non-@nogc function doesPointTo
  3. Bugzilla 17806: processAllocator getter will override set value if it was set before getter was called at least once
  4. Bugzilla 18415: Typedef ignores @disabled default constructor
  5. Bugzilla 18470: std.algorithm.splitter has frame access problems for custom preds
  6. Bugzilla 18525: Constraint on std.algorithm.mutation.remove fails with char[]
  7. Bugzilla 18760: theAllocator should hold a reference to the allocator that it uses
  8. Bugzilla 18847: std.allocator: Region uses .parent before it can be set
  9. Bugzilla 18934: std.concurrency receive throws assertion failure if message is a struct containing const data
  10. Bugzilla 18940: []Can't run examples on page. cannot implicitly convert expression ... char[] to string
  11. Bugzilla 18952: std.experimental.checkedint.Saturate prints integral promotion deprecation message
  12. Bugzilla 19020: findSkip, findSplit and findSplitBefore return wrong results
  13. Bugzilla 19023: findSplitBefore and findSplitAfter give wrong bool result

Phobos enhancements

  1. Bugzilla 18178: std.path should be usable in @safe
  2. Bugzilla 18593: std.datetime.stopwatch.benchmark shouldn't optimize away its functions
  3. Bugzilla 18766: std.typecons.Tuple.toHash could be improved
  4. Bugzilla 18813: fromStringz should work with char, wchar and dchar
  5. Bugzilla 18837: MMFile should have opDollar
  6. Bugzilla 18948: std.uni.toLower and std.uni.toUpper should work with random access ranges

Druntime regressions

  1. Bugzilla 18996: Inserting a type containing indirections into an std.container Array causes SIGILL(4). Illegal Instruction.
  2. Bugzilla 19005: [REG2.081-b1] object.hashOf no longer works for

Druntime bugs

  1. Bugzilla 14536: Calling destroy() on a on an extern(C++) class causes a segfault
  2. Bugzilla 18932: core.internal.hash.hashOf(val, seed) ignores seed when val is a raw pointer
  3. Bugzilla 18989: On OSX32, core.stdc.time.clock() should resolve to clock$UNIX2003()
  4. Bugzilla 19008: core.internal.convert.toUbyte doesn't work on enums

Druntime enhancements

  1. Bugzilla 18768: object.getArrayHash with custom toHash shouldn't just sum hashes of array elements
  2. Bugzilla 18920: core.internal.hash of array of scalars should be @safe
  3. Bugzilla 18924: Use addition rather than XOR for order-independent hash combination
  4. Bugzilla 18925: core.internal.hash auto-hash for structs of scalar fields should be @safe
  5. Bugzilla 18943: core.internal.hash remove outdated special case for DMD unaligned reads bugs

  1. Bugzilla 18752: runnable example fails
  2. Bugzilla 18761: Page for assumeUnique documentation displays incorrectly enhancements

  1. Bugzilla 14099: Promote DPaste ( to
  2. Bugzilla 18869: Add Jumia Food to organizations using D
  3. Bugzilla 18874: Add to organizations using D
  4. Bugzilla 18959: [Change Log: 2.079.0] substitute was added in std.algorithm.iteration but the changelog points to std.algorithm.searching

Contributors to this release (51)

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

previous version: 2.080.1 – next version: 2.081.1