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

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

2.085.0 comes with 20 major changes and 36 fixed Bugzilla issues. A huge thanks goes to the 35 contributors who made 2.085.0 possible.

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

Compiler changes

  1. Add support for Objective-C classes

    Prior to this release D interfaces were used to represent Objective-C classes. Now proper support for Objective-C classes has been added and D classes can be used instead to represent Objective-C classes. It's preferred to use D classes to represent Objective-C classes.

    This release also adds support for implementing Objective-C subclasses and methods in D.

    To match the behavior in Objective-C some additional changes have been made:

    • static and final methods are virtual. Although final methods are virtual it's not possible to override a final method in a subclass
    • static methods are overridable in subclasses


    extern (Objective-C)
    class NSObject
        static NSObject alloc() @selector("alloc");
        NSObject init() @selector("init");
        void release() @selector("release");
    extern (Objective-C)
    class Foo : NSObject
        override static Foo alloc() @selector("alloc");
        override Foo init() @selector("init");
        int bar(int a) @selector("bar:")
            return a;
    void main()
        auto foo = Foo.alloc.init;
        scope (exit) foo.release();
        assert( == 3);
  2. Add support for Objective-C instance variable

    It's now possible to declare instance variables in Objective-C classes.

    Instance variables in Objective-C are non-fragile. That means that the base class can change (add or remove instance variables) without the subclasses needing to recompile or relink. Thanks to this feature it's not necessary to declare instance variables when creating bindings to Objective-C classes.


    extern (Objective-C)
    class NSObject {}
    extern (Objective-C)
    class Foo : NSObject
        int bar;
        static Foo alloc() @selector("alloc");
        Foo init() @selector("init");
        void release() @selector("release");
        void getBar() @selector("getBar")
            return bar;
    void main()
        auto foo = Foo.alloc.init;
        scope (exit) foo.release(); = 3;
        assert(foo.getBar() == 3);
  3. Add support for Objective-C super calls

    It's now possible to implement an Objective-C method and make a super call to a method in the base class.


    extern (Objective-C)
    class NSObject
        void release() @selector("release");
    extern (Objective-C)
    class Foo : NSObject
        int foo() @selector("foo")
            return 3;
    extern (Objective-C)
    class Bar : Foo
        static Bar alloc() @selector("alloc");
        Bar init() @selector("init");
        override int foo() @selector("foo")
            return + 1;
    void main()
        auto bar = Bar.alloc.init;
        scope (exit) bar.release();
        assert( == 4);
  4. Deprecate Objective-C interfaces

    Prior to this release, it was necessary to represent an Objective-C class as a D interface. Now support for Objective-C classes has been implemented and the class keyword should be used instead.

    The reason for this deprecation is to allow extern (Objective-C) interfaces to be repurposed for representing Objective-C protocols in the future.


    extern (Objective-C) interface NSObject {} // deprecated

    Replace with:

    extern (Objective-C) class NSObject {}
  5. Context-aware assertion error messages

    With this release DMD supports generating context-aware assertion error messages when no error message has been provided by the user. For example, currently the following file:

    void main()
        int a, b = 2;
        assert(a == b);

    would yield this error when compiled and run:

    > dmd -run main.d
    core.exception.AssertError@main.d(4): Assertion failure
    ??:? _d_assertp [0x1c4eae48]
    onlineapp.d:4 _Dmain [0x1c4ead85]

    However, with the new experimental compiler switch -checkaction=context it yields:

    > dmd -checkaction=context -run main.d
    core.exception.AssertError@main.d(4): 0 != 2
    ??:? _d_assert_msg [0x4a3f9cf0]
    ??:? _Dmain [0x4a3f8fc4]

    The new switch already supports a variety of assertion messages:

    string dlang = "d2";
    assert(dlang != dlang); // ERROR: "d2" == "d2"
    struct S { int s; }
    assert(S(0) == S(1)); // ERROR: "S(0) !is S(1)"
    int a = 1, b = 2);
    assert(a > b); // ERROR: 1 <= 2

    Also if no error message can be generated, it will now fallback to displaying the text of the assert expression. For example, for this more complicated assert expression:

    void main()
        int a, b = 2;
        assert(a && (a == b));

    Compiling and running with -checkaction=context will now result in:

    > dmd -checkaction=context -run main.d
    core.exception.AssertError@main.d(4): assert(a && (a == b)) failed
    ??:? _d_assert_msg [0xb7e5fdfc]
    ??:? _Dmain [0xb7e5fd40]

    This switch for context-aware assertion error messages is still experimental and feedback is welcome.

  6. Avoid calling the struct constructor from const-casts

    In previous versions of DMD, there was an undocumented interaction of const-cast with regular cast, ie. cast(), cast(const) and cast(immutable), where these casts would be expressed as cast(const(typeof(expr))) expr; hence if expr was of type Struct, these casts could potentially call its constructor Struct(expr), as per spec.

    The dangerous part however, was if this occurred with structs that used their first field as alias this, the implicit conversion via alias this would potentially satisfy an implicit struct constructor, leaving the other fields set to init and leading to apparent data corruption from a mere cast().

    In other words, cast() s to S(s) to S(s.implicitCast).

    This can no longer occur, since cast(), cast(const) and cast(immutable) will no longer generate an implicit constructor call. Implicit constructor calls to S() will only occur when one explicitly uses cast(S).

  7. dmd now supports expressive diagnostic error messages with -verrors=context

    With the new CLI option -verrors=context dmd will now show the offending line directly in its error messages. Consider this faulty program test.d:

    void foo()
        a = 1;

    Now run it with -verrors=context:

    > dmd -verrors=context test.d
    test.d(4): Error: undefined identifier a
        a = 1;

  8. OSX 32-bit is no longer supported

    With this release, the DMD compiler will no longer officially support building 32-bit applications for OSX. For legacy purposes, older releases can be used.

    Motivation: The latest macOS release Mojave is the last version of OSX with support for running 32-bit applications. The D development team wants to focus its efforts and build/test infrastructure on active and important platforms.

Runtime changes

  1. Added GC.profileStats() to core.memory

    Allows access to current GC profiling information. See core.memory.GC.ProfileStats for a list of profile stats.

  2. Added core.stdcpp.new_

    Added core.stdcpp.new_, which exposes interfaces for C++ global new/delete operators. This allows D programs to conveniently allocate from the C++ heap, which is useful when sharing memory between languages.

  3. Added core.sys.linux.sched.CPU_COUNT.

    Added core.sys.linux.sched.CPU_COUNT, which returns the number of CPUs in set.

  4. Added core.sys.linux.sched.CPU_ISSET.

    Added core.sys.linux.sched.CPU_ISSET, which tests to see if cpu is a member of set.

  5. Moved std.conv.emplace, std.algorithm.mutation.move, std.algorithm.mutation.moveEmplace, and std.functional.forward to core/lifetime.d

    emplace is the counterpart to destroy, so it has been moved to also live in druntime (core/lifetime.d) where it is accessible by projects that use a shallow runtime library stack. move, moveEmplace, and forward are related low-level construction machinery which also belong in core.lifetime.

  6. GC cleanup can now be configured as a DRT GC option

    The default cleanup method for the GC is to unconditionally run a collection before runtime termination to finalize objects that are still alive and hold resources that affect system state outside the current process. This combines the worst of possible alternatives: it can cause a considerable delay and does not guarantee finalization of all objects as roots might still exist.

    The cleanup behaviour can now be configured by a DRT option to the GC configuration, e.g. by passing --DRT-gcopt=cleanup:none on the command line. Three options are provided:

    • collect: run a collection (the default for backward compatibility)
    • none: do nothing
    • finalize: all live objects are finalized unconditionally

    As usual, you can also embed the configuration into the application by redefining rt_options, e.g.

    extern(C) __gshared string[] rt_options = [ "gcopt=cleanup:none" ];
  7. GC.realloc is now more consistent and robust

    The specification of core.memory.GC.realloc has changed slightly:

    • GC.realloc now returns null for failure. (It used to return the original pointer but that is is not a good indication of failure as it might also be returned on success. It can lead to overwriting memory if an enlargement was requested.)
    • as with, the caller has to ensure that there are no other live pointers to the memory passed to GC.realloc (This used to be required only when passing a new size 0).
    • as a consequence the GC is allowed to free the memory immediately (the previous implementation did this for objects larger than 4kB when shrinking).
    • block attribute bits on the existing block are only set if it is reused (the previous implementation didn't set bits if it reused a small block).

    The implementation now properly verifies that pointers are actually base pointers to allocated GC memory (passing other pointers could have crashed immediately or corrupt the GC).

  8. Added core.stdcpp.allocator

    Added core.stdcpp.allocator, which exposes the C++ std::allocator<T> class. This is a required foundation for any of the allocating STL container types.

  9. char/wchar fields in most D runtime (core.* and rt.*) structs are now zero-initialized

    Fields that are single char/wchar or fixed-length arrays of such are now initialized to all zero bits instead of all one bits for most structs in the D runtime (core.* and rt.*` modules

    . This simplifies initialization and removes the need to store init data when it makes the entire struct zero-initialized. Most affected structs are used for interoperability with C APIs.

Dub changes

  1. extraDependencyFiles attribute added

    Using attribute extraDependencyFiles a list of files can be specified causing rebuild on change.

  2. File system supplier enabled

    Existing file system supplier is enabled for usage. It searches a certain directory for files with names of the form "[package name]-[version].zip".

    Example dub fetch mypackage --registry=file:///etc/dub/packages/

  3. toolchainRequirements recipe entry

    DUB now supports a new entry in dub.json or dub.sdl to restrict the versions of DUB and of compilers supported by a package.


        "toolchainRequirements": {
            "dub": "~>1.10",
            "frontend": ">=2.068|<2.083"


    toolchainRequirements dub="~>1.10" frontend=">=2.068|<2.083"

    Supported entries in toolchainRequirements are:

    • dub
    • frontend
    • dmd
    • ldc
    • gdc

    Each can be assigned to one or more version specifications, separated by |. For compilers, instead of a version specification, the keyword no can also be used to indicate that the compiler should not be used for this package.

    Example scenario:
    Package that needs DUB>=1.12, and that will only build with LDC>=1.10:


        "toolchainRequirements": {
            "dub": ">=1.12",
            "dmd": "no",
            "gdc": "no",
            "ldc": ">=1.10"


    toolchainRequirements dub=">=1.12" dmd="no" gdc="no" ldc=">=1.10"

List of all bug fixes and enhancements in D 2.085.0:

DMD Compiler regressions

  1. Bugzilla 16214: [REG2.069] ICE: Assertion `fd->semanticRun == PASSsemantic3done' failed.
  2. Bugzilla 16652: [Reg 2.071] returned rvalue destroyed too early
  3. Bugzilla 17518: [Reg 2.063] confusing error message with inout constructor/ctor
  4. Bugzilla 18372: REG(2.072): error missing line number: Error: undefined identifier __va_list_tag
  5. Bugzilla 19494: [REG 2.080.0][objc] interface main.NSObject.Class conflicts with interface main.NSObject.Class
  6. Bugzilla 19499: __c_long_double has exact match with double

DMD Compiler bugs

  1. Bugzilla 16098: align(32) not respected for stack variables
  2. Bugzilla 17090: dmd -transition=? needs quoting => make it -transition=help
  3. Bugzilla 17181: Local imports in templates should be added to imported modules list of module that instantiated it
  4. Bugzilla 18545: Casting away const with cast() triggers alias this, but returns the supertype anyway
  5. Bugzilla 19549: -check=in=off doesn't work
  6. Bugzilla 19551: corrupt ELF library when using pragma(crt_constructor)

DMD Compiler enhancements

  1. Bugzilla 19097: Extend Return Scope Semantics
  2. Bugzilla 19543: Shared object "" not found, required by "dmd"
  3. Bugzilla 19552: -transition is non-intuitive to use - the flag should list options by default

Phobos bugs

  1. Bugzilla 18519: freebsd 11 + phobos + curl, timing out
  2. Bugzilla 18913: Cannot move static array of non-copyable type
  3. Bugzilla 19572: std.array.Appender.put invokes struct constructor via cast
  4. Bugzilla 19580: [non-DMD] std.random seed bootstrap: don't count on reading an uninitialized variable being treated as an ordinary read

Phobos enhancements

  1. Bugzilla 19453: Remove unnecessary error checks in std.datetime.systime.currStdTime()
  2. Bugzilla 19526: make std.typecons.RefCounted work in betterC

Druntime bugs

  1. Bugzilla 11393: [GC] GC realloc and free don't ignore interior pointers
  2. Bugzilla 11446: [GC] GC realloc doesn't ignore non-GC owned pointers
  3. Bugzilla 12843: Unit tests fail when GC is compiled with SENTINEL
  4. Bugzilla 15393: Debug versions in GC code doesn't compile.
  5. Bugzilla 17431: GCBits should be @nogc to prevent deadlocks
  6. Bugzilla 19281: GC mishandles allocations >= 4GB
  7. Bugzilla 19522: [GC] GC.query/addrOf/sizeOf fail for freed memory
  8. Bugzilla 19562: core.internal.hash.hashOf array of pointers or delegates should be @safe
  9. Bugzilla 19568: hashOf should not unnecessarily call a struct's fields' postblits & dtors in CTFE
  10. Bugzilla 19571: Incorrect definition of DTM_FIRST in
  11. Bugzilla 19582: Make core.internal.convert.toUbyte in CTFE for arrays work with reference type elements and not call postblits/dtors

Druntime enhancements

  1. Bugzilla 16377: Make --DRT GC profile information available outside of GC destruction
  2. Bugzilla 19128: argument to alloca may be too large
  3. Bugzilla 19455: GC wastes too much memory
  4. Bugzilla 19524: Make core.checkedint work in betterC

Contributors to this release (35)

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

previous version: 2.084.0