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

previous version: 2.101.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.102.0 comes with 29 major changes and 102 fixed Bugzilla issues. A huge thanks goes to the 41 contributors who made 2.102.0 possible.

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

Compiler changes

  1. Add bit fields to D

    They work just like the bit fields in ImportC do.

    struct B
        int x:3, y:2;
    static assert(B.sizeof == 4);
    int vaporator(B b)
        b.x = 4;
        b.y = 2;
        return b.x + b.y; // returns 6
  2. Added __traits(classInstanceAlignment)

    To complement __traits(classInstanceSize), providing the required alignment for manual buffers etc.:

    align(__traits(classInstanceAlignment, C))
    void[__traits(classInstanceSize, C)] buffer;
  3. Relaxed pragma(crt_constructor) / pragma(crt_destructor) linkage check

    extern(C) isn't a requirement for CRT con/destructors anymore when using the default void () signature.

  4. Add predefined version D_Optimized when compiling with -O

    It allows code to distinguish whether it's being compiled with optimizations enabled (the -O flag was provided). This is orthogonal to whether -release mode is active - for that see the predefined versions assert, D_NoBoundsChecks, D_Invariants, etc.

  5. Throwing from contracts of nothrow functions has been deprecated

    Up until now, the compiler accepted in and out contracts of nothrow functions to throw exceptions and call throwing functions. As this breaks nothrow guarantees, a deprecation notice is now triggered.

    // deprecated:
    float sqrt(float n) nothrow
        if (n < 0)
            throw new Exception("n must be positive");
        // ...
    // fix: remove nothrow attribute or use assertions
    float sqrt(float n) nothrow
        assert(n >= 0);
        // ...
  6. Using integers for version or debug conditions has been deprecated

    The problem is that it only provides a single number namespace without any meaning. It's better to use version identifiers describing the feature they enable. See also this thread on the forum.

    // now deprecated:
    version = 3;
    version (2) { }
    debug = 4;
    debug (5) { }
    // use identifiers instead:
    version = HasX;
    version (HasX)
        void x() { /* ... */ }
        void x() {}
  7. Print deprecations for scope pointer errors

    The scope attribute has existed for a long time, but the compiler would only verify its semantics when the -preview=dip1000 switch was passed, to avoid breaking code. Pointers or references stored in a scope variable are not allowed to escape the scope in which the variable is defined.

    Usually, it is not necessary to mark variables scope, since the Garbage Collector (GC) takes care of freeing memory. However, D allows creating pointers / slices that point to local variables, which use Stack-based memory allocation and are destructed at the end of their scope. It is important that in @safe code, creating such pointers is either disallowed, or has scope semantics enforced, but the compiler would formerly fail to do that:

    int[] getSlice()
        int[4] stackBuffer;
        int[] slice = stackBuffer[]; // slice points to local variable allocated on stack
        return slice; // dangling pointer!
    struct S
        int x;
        int* get()
            int* y = &this.x; // this struct instance could be a local variable
            return y; // dangerous!

    Starting with this release, scope semantics are enforced in @safe code on pointers to stack memory, but only as deprecation warnings. Eventually, they will be turned into errors. To turn them into errors immediately, use -preview=dip1000. To disable the deprecations, use -revert=dip1000.

    Note that the original DIP1000 text is outdated, so please refer to the specification pages for documentation:

  8. Improvements for the C++ header generation

    The following features/bugfixes/improvements were implemented for the experimental C++ header generator:

    • Overriding virtual functions are now marked with the override keyword when generating C++11 compatible headers.
    • Final virtual functions are now marked with the final keyword when generating C++11 compatible headers.

    Note: The header generator is still considered experimental, so please submit any bugs encountered to the bug tracker.

  9. -preview=fixImmmutableConv has been added

    The compiler allows implicitly converting a return value with indirections to immutable if it determines the result must be unique. Formerly, this check would inspect the types of the indirections, and forget to take into account conversions, such as int[] to void[]:

    int[] f(ref void[] m) pure
        auto result = new int[5];
        m = result;
        return result;
    void main()
        void[] v;
        immutable x = f(v);
        // `v` is now a mutable alias to immutable variable `x`

    This was filed as issue 15660, which has been fixed some time ago by making the check more strict: the called function must be strongly pure. However, to avoid breaking code, the fix was only active with the -preview=dip1000 switch. Since it is unrelated to dip1000 (which is about scope pointers), the fix has been moved to a new -preview=fixImmmutableConv switch.

  10. Returning a discarded void value from a function is now deprecated

    An expression statement of type void that has no side effects should be discarded since it has no effect. The compiler, generally, does not allow such statements, however, in the case of return statements this error is circumvented. For example:

    struct StackBuffer
        auto opIndex(size_t i)
            return arr[i];
        void[] arr;

    Although this code compiles, any call to opIndex is going to result in an error because the return type must either be stored somewhere (and variables cannot be of type void) or the call will have no effect.

    Starting with this release, returning a discarded void value from a function is deprecated. Such code can be deleted as it most certainly is dead code.

  11. ImportC now recognizes the typeof(...) operator

    ISO C does not specify a typeof operator, but it is a widely-implemented vendor extension. ImportC now implements this extension as well.

    Only the form typeof(...) is recognized, other compilers also support (or only support one of) __typeof__(...) and __typeof(...). Imported C using these forms will need to be normalized with #defines.

  12. Removed the -transition=markdown and -revert=markdown switches

    This release removes the -transition=markdown, which prints markdown substitutions made when processing markdown in ddoc documentation blocks, and -revert=markdown switches which disables markdown substitutions in ddoc documentation blocks.

    Markdown substitutions have been the default for some time now, and as of this release is always performed.

  13. new can now allocate an associative array

    This allows two associative array references to point to the same associative array instance before any keys have been inserted.

    int[string] a = new int[string];
    auto b = a;
    a["seven"] = 7;
    assert(b["seven"] == 7);

    Note: Calling new is not needed before inserting keys on a null associative array reference - the instance will be allocated if it doesn't exist.

  14. -preview=in can now be used with extern(C++), disabled for other non-D linkage

    The intent of -preview=in is to make in the go-to storage class for input parameters in D. However, it is D centric, as it is an enhanced version of scope const ref. As non-extern(D) functions usually are expected to match a specific ABI, using in is hardly a good idea.

    As C++ also has a "go to" storage class for input parameters (const T&), in can also be applied on extern(C++) function in order to bind to const T& parameters. This also allows to expose a closer API for a function than via const ref, as in will allow to bind rvalues to const T&, as in C++.

  15. The shortened method syntax is now available by default.

    DIP 1043---Shortened Method Syntax has been accepted, the flag -preview=shortenedMethods is no longer required to write shortened function bodies:

    int add(int x, int y) pure => x + y;
    // equivalent full function body:
    int add(int x, int y) pure
        return x + y;

    The preview flag will still work until it is deprecated in a future release.

  16. Source files may no longer contain Unicode directionality overrides

    Trojan Source: Invisible Vulnerabilities shows how they can be used to maliciously hide code in various programming languages. D is also affected.

    To prevent this, the compiler now raises an error when they appear in source files. If you need a string literal containing directionality overrides, use escape sequences instead:

    string s = "\u202E\u2066";
  17. Windows: Double DMD stack limit to 16 MB

    The compilation of some projects require more stack space than previously available. Now DMD has the same limit as LDC, which increased its stack limit in its 1.29.0 release.

Runtime changes

  1. Added avx512f detection to core.cpuid

    The feature flag core.cpuid.avx512f has been added to allow detection at run-time CPUs with 512-bit vector support.

  2. --DRT-oncycle=deprecate is removed

    The option was introduced in 2.072.2 to help transition code that relied on the old faulty cycle checker for module constructors. It now prints a warning and does the same as the default, --DRT-oncycle=abort. See also: Order of Static Construction in the specification.

  3. Posix (excl. Darwin): Switch default GC signals from SIGUSR1/2 to SIGRTMIN/SIGRTMIN+1

    As the SIGUSR ones might be used by 'system' libraries (e.g., Android Dalvik VM or LLVM libFuzzer), while the SIGRT ones are reserved for user-defined purposes and less likely to collide.

    The used signals can still be customized with an early call to core.thread.osthread.thread_setGCSignals().

Library changes

  1. Added SafeRefCounted, that can be used in @safe with -preview=dip1000.

    RefCounted is only available for @system code, because of the possibility of escaping a reference to its payload past the end of its lifetime. a modified copy of it, std.typecons.SafeRefCounted has been added. Also added is a borrow function, that lets one safely access and modify the payload. -preview=dip1000 prevents escaping a reference to it in @safe code.

    @safe pure nothrow void fun()
        import std.typecons;
        auto rcInt = safeRefCounted(5);
        assert(rcInt.borrow!(theInt => theInt) == 5);
        auto sameInt = rcInt;
        assert(sameInt.borrow!"a" == 5);
        // using `ref` in the function
        auto arr = [0, 1, 2, 3, 4, 5, 6];
        sameInt.borrow!(ref (x) => arr[x]) = 10;
        assert(arr == [0, 1, 2, 3, 4, 10, 6]);
        // modifying the payload via an alias
        assert(rcInt.borrow!"a" == 10);

    Direct access to the payload unfortunately has to be @system, though. While -dip1000 could prevent escaping the reference, it is possible to destroy the last reference before the end of it's scope:

    int destroyFirstAndUseLater()
        import std.typecons;
        auto rc = SafeRefCounted!int(123);
        int* ptr = &rc.refCountedPayload();
        return *ptr; // Reads from freed memory. Don't do this.

    As a side effect, this enabled us to make std.file.dirEntries @safe with -preview=dip1000.

    Some member functions of RefCounted that are @safe are not so in SafeRefCounted. The RefCounted type and refCounted function are still available for the old behaviour. However, their main purpose is backwards compatibility. They are not recommended for new code.

  2. Move logger out of experimental.

    The std.experimental.logger package is now std.logger. The old package and modules are still available and publicly import the new ones. To avoid breakage in modules that compile with deprecations as errors, for now the old modules aren't deprecated, but they will be.

  3. remove std.experimental.logger's capability to set the minimal LogLevel at compile time

    Before this change std.experimental.logger had the capability to disable logging at compile time. It was also possible to set the minimal LogLevel at compile time. The trade-off between gained capability, added complexity, and error-proneness was too heavily tilted towards the second two items. This change removes these compile time features.

  4. Change std.experimental.logger.core.sharedLog to return shared(Logger)

    To make unsafe code more explicit std.experimental.logger.sharedLog now returns a shared(Logger) instead of a Logger.

  5. std.experimental.typecons has been removed

    This was an attempt to update std.typecons.wrap with an implementation that could work with struct, but it did not go anywhere. See this post on the forum.

  6. std.digest.digest has been removed

    This module was initially deprecated in 2.076.1, and has been empty since 2.092.0 when all deprecated symbols were removed in favour of importing std.digest or its submodules instead.

  7. std.xml has been removed

    This module is considered out-dated and not up to Phobos' current standards. If you still need it, go to

  8. std.socket.Socket methods now accept only scope arrays.

    To comply with dip1000, std.socket.Socket methods now all have scope attributes applied to any slice parameters. This includes receive and send flavors, and also setOption. While not technically a breaking change for users of Socket, if you derive from it, you must apply those attributes to your derivatives or it will fail to compile. However, applying the attributes is backwards compatible with previous versions of Phobos, so there is no need for a migration path.

  9. Add custom fill value to std.outbuffer.OutBuffer class

    Extend the fill, alignSize, align{2,4} methods of std.outbuffer.OutBuffer to specify value to write when filling (up to an alignment).

    For flash device images it is desirable to use 0xff as the fill value, because 0xff is the value of the unprogrammed flash memory cell. Padding with 0 requires to programm the flash cell from 0xff to 0x00, which increases wear and tear on the flash memory device. Usually there is some larger block at the end if the flash memory image, which must be padded up to the size of the flash device (usually a power of two). Instead of padding with 0x00 the PR allows to fill with 0xff instead.

    There might be also some other use-cases, where it might be reasonable to fill the alignment gaps with some other value than 0x00, e.g. when debugging and viewing output data in a hex editor. It is easier to spot gaps, when the padded spaces contain a custom value like 0x55 or 0xaa.

    A new fill method was added, which allows filling with a user-defined value instead of the 0 as in the previous implementation.

    OutBuffer buf = new OutBuffer();
    buff.fill( 1234, 42 ); // Fills 1234 bytes with 42 starting at buf.offset
    buff.fill( 10 );       // Same as fill0( 10 );

    The alignSize, align{2,4} methods were modified to use some user-defined value for padding to the requested alignment boundary.

    OutBuffer buf = new OutBuffer();
    buf.write(cast(ubyte) 1);
    assert(buf.toBytes() == "\x01\x55");
    buf.write(cast(ubyte) 2);
    assert(buf.toBytes() == "\x01\x55\x02\x55");
    buf.write(cast(ubyte) 3);
    buf.alignSize(8, 0x55);
    assert(buf.toBytes() == "\x01\x55\x02\x55\x03\x55\x55\x55");

List of all bug fixes and enhancements in D 2.102.0:

DMD Compiler regression fixes

  1. Bugzilla 18646: [REG 2.079.0] Recursive template expansion incorrectly reported
  2. Bugzilla 19268: BetterC turns off .dup for CTFE
  3. Bugzilla 20520: Runtime segfault when taking typeid of a class instanciated within an enum
  4. Bugzilla 20811: Regression as of 2.066.0 - CTFE static variable retained across calls
  5. Bugzilla 21301: Wrong values being passed in long parameter list
  6. Bugzilla 22638: [REG 2.096][ICE] cod4.d: Assertion cast(int)sz > 0 failed
  7. Bugzilla 22646: [REG2.099] CT bounds checking ignores short circuit evaluation
  8. Bugzilla 22813: [REG 2.079.1] recursive template expansion
  9. Bugzilla 22854: static foreach byCodepoint segfault (2.099-rc.1)
  10. Bugzilla 22975: 3 cyclic aliases with meaningful overloads not caught [ice]
  11. Bugzilla 23307: [REG][CODEGEN][SIMD] wrong codegen with inlined local functions + SIMD
  12. Bugzilla 23391: [Reg 2.098.1] Segmentation fault with static foreach + range + inout
  13. Bugzilla 23490: DMD creating corrupted vtable
  14. Bugzilla 23497: Erroneous escape reference to parameter error.
  15. Bugzilla 23499: inliner crashes/asserts when building for 32-bit
  16. Bugzilla 23532: Missing type properties for complex special enum types
  17. Bugzilla 23539: [REG master] Scope C++ definition out of sync with D
  18. Bugzilla 23548: [REG 2.098] C sources files have precedent over D modules in imports
  19. Bugzilla 23549: assert(0) as default parameter causes segfault
  20. Bugzilla 23564: [REG 2.099.0] SIGSEGV during compilation
  21. Bugzilla 23567: pragma(printf) messes up with the vtable of extern(C++) classes
  22. Bugzilla 23569: [REG 2.081][ICE] Segmentation fault in in AggregateDeclaration::getType() (this=0x0) at src/dmd/aggregate.d:594
  23. Bugzilla 23587: cast(void) doesn't work for noreturn
  24. Bugzilla 23589: [REG2.095] Purity check special case gives circular reference error.
  25. Bugzilla 23591: [REG 2.101] Invalid casts accepted by the compiler if from type is noreturn
  26. Bugzilla 23607: invalid code leading to an ICE due to an error message that's not emitted anymore
  27. Bugzilla 23626: [REG2.096] Template deduction with auto const ref Args... and delegate

DMD Compiler bug fixes

  1. Bugzilla 13060: @nogc reading an associative array
  2. Bugzilla 14907: DMD crash when using template name as a default value of template's typed argument
  3. Bugzilla 15414: __traits(getAttributes) should error if the function has multiple overloads
  4. Bugzilla 15712: extern(C) attribute inside extern(C) unittest is incorrectly ignored
  5. Bugzilla 18026: Stack overflow in ddmd/dtemplate.d:6241, TemplateInstance::needsCodegen()
  6. Bugzilla 19585: Invalid recursive template expansion error
  7. Bugzilla 19623: HERE string identifier cannot start with Unicode letter
  8. Bugzilla 19649: Misleading error message for duplicate constraints
  9. Bugzilla 21062: Confusing error when using a keyword as an identifier for a declaration
  10. Bugzilla 21506: misalignment of _argptr for variadic functions
  11. Bugzilla 21613: DMD crash: copy ctor + templated rvalue ctor
  12. Bugzilla 22587: ternary with function call and assert(0) leads to cod1 assertion
  13. Bugzilla 22759: ImportC: cannot modify const expression from dereferencing const pointer declared within function.
  14. Bugzilla 23122: enum member UDAs semantics are not checked properly
  15. Bugzilla 23151: ICE: core.exception.AssertError@src/dmd/aggregate.d(678): Assertion failure
  16. Bugzilla 23218: ICE: src/dmd/backend/cgxmm.d:1373: Assertion `0' failed.
  17. Bugzilla 23412: void init member detection does not account for static arrays
  18. Bugzilla 23418: double argument is passed on stack, but assumed to be in XMM0 register
  19. Bugzilla 23447: wrong expression in error message when template instance doesn't match any overload
  20. Bugzilla 23462: dmd: src/dmd/backend/cod2.d:2158: Assertion cast(int)tysize((*e).Ety) <= REGSIZE() failed
  21. Bugzilla 23463: Don't count skipped function overloads when limiting overloads shown
  22. Bugzilla 23465: Invalid token error points to wrong line
  23. Bugzilla 23470: Backticks in diagnostic are confusing with wrong number of arguments passed
  24. Bugzilla 23481: [inf loop] usertype enums opOpAssign cause an compile time infinite loop
  25. Bugzilla 23491: Nonsensical deprecation message when using delegate
  26. Bugzilla 23516: Anonymous enum without base type causes segfault inferring member value
  27. Bugzilla 23529: [ICE] Compiler segfaults on static array cast
  28. Bugzilla 23531: [DIP1000] scope variable can be assigned as AA key
  29. Bugzilla 23533: Segmentation fault accessing enum.max with -preview=nosharedaccess
  30. Bugzilla 23534: __traits(isZeroInit) is true for enums with explicit values
  31. Bugzilla 23536: crt_constructors and crt_destructors should not be non-static member functions
  32. Bugzilla 23568: Error: cannot implicitly convert expression 'a < b' of type 'float4' to 'int4'
  33. Bugzilla 23574: ICE: AssertError@src/dmd/optimize.d(866): Assertion failure
  34. Bugzilla 23578: Types are not matched to alias parameters in "is" expression
  35. Bugzilla 23586: DMD forgets a variable was just declared.
  36. Bugzilla 23593: core.thread: suspendAll doesn't wait for all if current thread has detached itself
  37. Bugzilla 23614: ImportC: __int128 not supported
  38. Bugzilla 23618: Right Shift equals expressions on unsigned shorts should be unsigned right shift
  39. Bugzilla 23620: 'alias this' is not respected in static array length position

DMD Compiler enhancements

  1. Bugzilla 9848: Better diagnostic when type declaration was not expected
  2. Bugzilla 15368: Improve error message for "auto" keyword inside "foreach"
  3. Bugzilla 21338: Confusing error message for template overload resolution failure
  4. Bugzilla 22306: scope array variable should be stack allocated
  5. Bugzilla 23410: ImportC: binary constants not allowed
  6. Bugzilla 23424: improve error when template instantiation doesn't match any overload
  7. Bugzilla 23458: No template candidates listed when OverDeclaration or OverloadSet don't match
  8. Bugzilla 23466: -verrors=context should not repeat same context for supplemental messages
  9. Bugzilla 23480: non-empty ForStatement Increment clause should require a side effect
  10. Bugzilla 23552: Function x does not override any function, but it actually does
  11. Bugzilla 23566: ImportC: __PRETTY_FUNCTION__ is not defined

Phobos bug fixes

  1. Bugzilla 22745: std.parallelism.parallel fails to process empty range on a single CPU
  2. Bugzilla 23319: std.range.Generator does not work with non-mutable elements
  3. Bugzilla 23488: std.format.sformat mishandles char ranges
  4. Bugzilla 23507: Socket.blocking property incorrect on new Socket on Windows
  5. Bugzilla 23540: std.uni loadProperty aliases for C are incorrect
  6. Bugzilla 23561: std.typecons.Unique!struct does not destroy struct instance
  7. Bugzilla 23640: Nullable range iteration doesn't work with immutable values

Phobos enhancements

  1. Bugzilla 19737: [std.experimental.allocator] link table in docs has missing symbols
  2. Bugzilla 23453: Generic iota should be a forward range

Druntime regression fixes

  1. Bugzilla 22616: Infinity loop instead of InvalidMemoryOperationError during GC routine
  2. Bugzilla 23562: [REG master] Segmentation fault in core.demangle

Druntime bug fixes

  1. Bugzilla 16641: Infinite loop on InvalidMemoryOperationError in __dmd_personality_v0
  2. Bugzilla 19467: Support EV_SET on OSX
  3. Bugzilla 23572: OpenBSD: Add OpenBSD to the RTLD_DEFAULT list

Druntime enhancements

  1. Bugzilla 20650: Cryptic error message when GC called in finalizer
  2. Bugzilla 23332: core.sync.condition notify methods should be @nogc
  3. Bugzilla 23498: OpenBSD: Fix core.sys.posix.sys.wait bug fixes

  1. Bugzilla 23382: Non-template requirement for copy constructors is undocumented
  2. Bugzilla 23436: Spec falsely states mutable references in struct .init are forbidden
  3. Bugzilla 23541: [ImportC] contains incorrect links enhancements

  1. Bugzilla 23426: Example Run button shows wrong line numbers for errors
  2. Bugzilla 23432: document when array capacity is zero and capacity performance
  3. Bugzilla 23511: Incrementing a not supported type in enum
  4. Bugzilla 23553: opCmp spec is incomplete

Installer bug fixes

  1. Bugzilla 23623: On 64 bit Windows the path should point to 64 bit dmd.

Contributors to this release (41)

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

previous version: 2.101.0