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

previous version: 2.100.2

Download D 2.101.0
released Nov 14, 2022

2.101.0 comes with 40 major changes and 64 fixed Bugzilla issues. A huge thanks goes to the 63 contributors who made 2.101.0 possible.

List of all bug fixes and enhancements in D 2.101.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");

Dub changes

  1. Building the special test runner configuration

    dub build --config=unittest --build=unittest[-cov] can now be used to mimic building the test runner executable of dub test [--coverage]. Note that this doesn't require an existing unittest configuration.

    dub describe --config=unittest allows to derive the path to the executable.

  2. Output will now be colorized

    Dub output has been improved to be more human readable, which means the most important informations in the output will now be colorized / bold.

    As is usual with CLI tools, this behavior is automatically turned on whether the output is a TTY. To force the old output in the presence of a TTY, use --color=off. To force colored output in the absence of a TTY, use --color=on.

    The --color flag, if set to on or off, is automatically forwarded to the compiler. This is especially useful for CI pipelines to ensure human-readable output.

  3. dub will now warn on unrecognized fields in dub.json, settings, or selections file

    Previously, dub was silently accepting anything it didn't recognize in dub.json, [dub.]settings.json and dub.selections.json. While the original intent was to make forward-compatibility easy, it proved detrimental as typos would just mean the user setting was ignored.

    From this release, dub will now warn about any entry in its configuration files or in dub.selections.json. After 10 releases, those warnings will turn into errors.

  4. The two new build types cov-ctfe and unittest-cov-ctfe have been added.

    These extend the existing build types cov and unittest-cov respectively by appending -cov=ctfe to the set of flags passed to the compiler.

  5. DUB settings & packages directory placement overhauled

    You can now configure where DUB places its downloaded packages and where the user configuration is stored through environment variables or through the dub configuration. You need to use an environment variable or the system-wide dub configuration to specify where the user configuration is stored.

    By default DUB stores the packages on

    • Windows: %APPDATA%/dub/settings.json + %LOCALAPPDATA%/dub/packages/
    • Posix: $HOME/.dub/{packages/,settings.json}

    now if the DUB_HOME environment variable is set it instead stores the packages (and other config) in

    • $DUB_HOME/{packages/,settings.json}

    alternatively if DUB_HOME isn't set, but DPATH is set, the following path is used:

    • $DPATH/dub/{packages/,settings.json}

    The DPATH environment variable is intended to be used by all D tooling related things doing user-space installation of things. It can be used to avoid cluttering the home folder.

    Additionally to environment variables it is possible to configure the package placement path + settings.json path through DUB's settings.json file. To configure where the user-editable settings.json is placed you need to adjust the system-wide dub configuration.

    In the settings.json you can set the following fields:

        "dubHome": "/path/to/dub", // sets both package store and config location

    Additionally, these config paths will have environment variables using the $VARIABLE syntax resolved.

    The following list describes which path is going to be picked, from top to bottom, stopping whenever one is found:

    • $DUB_HOME environment variable
    • $DPATH environment variable
    • system-wide settings.json: "dubHome" property (only for userSettings)
    • most specific settings.json: "dubHome" property (only for localRepository)

  6. DUB command exit codes have been made more consistent

    Some dub commands have been adjusted to return exit code 2 instead of exit code 1. Exit code 1 is now always used for usage errors, while exit code 2 is the more generic any error occurred or package failed to load.

    The following commands are affected:

    • dub clean
    • dub add
    • dub search
    • dub convert

  7. 'install' and 'uninstall' commands have been removed

    Those commands were long-deprecated aliases to fetch and remove, respectively, and usage of them triggered a warning. They are no longer listed as command in help and dub will no longer recognize them.

  8. When copyFiles is used to copy read-only files, it now makes the copy writable.

    Previously, if the target file would already exist due to a prior run of Dub, copyFiles would produce an access denied error because the read-only target could not be overwritten. Note that if you were affected by this behaviour, you will need to remove those files by hand once to eliminate these errors.

    It is common for version control systems to mark binary files read-only in the working copy, to prevent concurrent edits of files in unmergeable formats.

  9. The override system is deprecated

    Dub had an "override" system, allowing a specific version or version range to be overriden by a specific package. This override system was developed with a purely version-based approach in mind, however since its inception, more ways to specify dependencies have been added, making the override approach redundant and less flexible than other approaches. From this release, dub will warn you if it finds an override file, or when using the dub add-override / dub remove-override commands.

  10. The shortcut syntax for "dub run" is now also available for sub packages.

    Invoking dub as "dub :subpackage" is now equivalent to "dub run :subpackage", analogous to just "dub" being equivalent to "dub run".

  11. Upgrading all sub packages at once

    A new "-s" switch allows to "dub upgrade" all sub packages together with the base package. This aims to provide a better workflow for fully reproducible builds and tests.

List of all bug fixes and enhancements in D 2.101.0:

DMD Compiler regression fixes

  1. Bugzilla 23291: Members of arrays of shared classes cannot be compared

DMD Compiler bug fixes

  1. Bugzilla 23213: ImportC - variable length array does not compile
  2. Bugzilla 23340: std.path: expandTilde erroneously raises onOutOfMemory on failed getpwam_r()

Phobos regression fixes

  1. Bugzilla 23245: [REG 2.099] std.format ignores non-const toString method of static array element
  2. Bugzilla 23246: [REG 2.099] std.format ignores non-const toString method of associative array value
  3. Bugzilla 23268: clamp no longer accepts shorts
  4. Bugzilla 23400: [REG 2.099] Can't format enum value whose base type has non-const opEquals

Phobos bug fixes

  1. Bugzilla 14543: std.algorithm.searching.until does not handle range sentinels nicely
  2. Bugzilla 16034: map should be possible with a reference only
  3. Bugzilla 16232: std.experimental.logger.core.sharedLog isn't thread-safe
  4. Bugzilla 18631: std.random.choice does not work with const arrays
  5. Bugzilla 22637: std.conv to!double and parse!double dont throw on under/overflow
  6. Bugzilla 23182: Can't assign struct with opAssign to SumType in CTFE
  7. Bugzilla 23196: File constructor fails to preallocate oom error, uses exception instead
  8. Bugzilla 23215: calling std.file.remove with null string segfaults in strlen
  9. Bugzilla 23250: Unicode regional indicators are not paired correctly
  10. Bugzilla 23270: std.random.dice is poorly documented
  11. Bugzilla 23288: zlib: Fix potential buffer overflow
  12. Bugzilla 23324: Incorrect source link in std.format docs
  13. Bugzilla 23350: Nondeterministic test failure in std.concurrency
  14. Bugzilla 23362: Permutations should be a forward range

Phobos enhancements

  1. Bugzilla 13893: "rawRead must take a non-empty buffer"
  2. Bugzilla 18735: all versions of find and canfind should identify usage of predicate
  3. Bugzilla 21000: -preview=nosharedaccess precludes use of stdin,stdout,stderr
  4. Bugzilla 23101: [std.sumtype] canMatch does not account ref
  5. Bugzilla 23298: std.string wrap wraps early
  6. Bugzilla 23333: DList range can be @nogc
  7. Bugzilla 23370: std.base64 can have more @nogc functions

Druntime bug fixes

  1. Bugzilla 15939: GC.collect causes deadlock in multi-threaded environment
  2. Bugzilla 23060: MacOS: core.sys.posix.sys.socket missing some definitions
  3. Bugzilla 23065: importC: __builtin_expect should use c_long
  4. Bugzilla 23067: importC: offsetof macro assumes size_t is defined
  5. Bugzilla 23129: object.destroy doesn't consider initialize=false on D classes
  6. Bugzilla 23228: OpenBSD: No SIGRTMIN or SIGRTMAX
  7. Bugzilla 23302: std.algorithm.comparison.predSwitch producing SwitchError with error message as the filename

Druntime enhancements

  1. Bugzilla 23456: OpenBSD: Add waitid support bug fixes

  1. Bugzilla 14542: Table of contents in specification PDF is broken
  2. Bugzilla 15379: "final" attribute on function parameter
  3. Bugzilla 15476: DDOC_UNDEFINED_MACRO is undocumented
  4. Bugzilla 17324: Floating point 1/(1/x) > 0 if x > 0 not generally true
  5. Bugzilla 17514: "positive" -> "nonnegative"
  6. Bugzilla 17623: Unexpected failure of an assertion on empty strings
  7. Bugzilla 18496: Complement expressions now actually int promote
  8. Bugzilla 18855: Behavior of Anonymous Union is Undocumented
  9. Bugzilla 18887: inout badly described
  10. Bugzilla 19869: FunctionLiteral allows incorrect forms
  11. Bugzilla 21188: Anonymous structs - not described
  12. Bugzilla 21279: cast expression between integer types is not defined
  13. Bugzilla 21781: [Oh No! Page Not Found] Links to core libs from Better C
  14. Bugzilla 22237: AA.update is underspecified
  15. Bugzilla 22835: Undocumented type specializations of is-expression
  16. Bugzilla 23062: Function/delegate inference example does not compile
  17. Bugzilla 23194: Add our company to the list of D firms
  18. Bugzilla 23237: dmd 2.100.1 download link error.
  19. Bugzilla 23276: DOC: ">" instead of ">" in dmd-windows.html
  20. Bugzilla 23296: Value Range Propagation not documented
  21. Bugzilla 23314: Language spec falsely states that struct field invariants are checked
  22. Bugzilla 23325: Assigning dynamic array to static array not documented
  23. Bugzilla 23358: Link unusable due to space insertion enhancements

  1. Bugzilla 15286: is(typeof(symbol))
  2. Bugzilla 19036: .tupleof order guarantee
  3. Bugzilla 22141: Property .capacity is not listed in the array properties section
  4. Bugzilla 23186: wchar/dchar do not have their endianess defined
  5. Bugzilla 23359: Rename InOut to ParameterStorageClass

Contributors to this release (63)

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

previous version: 2.100.2