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

previous version: 2.106.1 – next version: 2.107.1

Download D 2.107.0
released Feb 01, 2024

2.107.0 comes with 10 major changes and 61 fixed Bugzilla issues. A huge thanks goes to the 37 contributors who made 2.107.0 possible.

List of all bug fixes and enhancements in D 2.107.0.

Compiler changes

  1. A string literal as an assert condition is deprecated

    Boolean evaluation of a string literal could happen unintentionally e.g. when an assert(0, "message") was meant and the 0 was missing.

    assert("unexpected runtime condition");
    static assert("unhandled case for `", T, "`");

    The 2 asserts would silently always have no effect. Now these cases will be detected with deprecation messages. If the original behaviour was actually intended, use expr !is null instead:

    assert("" !is null);
    static assert("" !is null);
  2. Makefiles cleanup for the compiler

    The Makefiles for building the compiler (compiler/src/{posix,win32,win64}.mak) have been deprecated for a while, and finally removed. Please use the compiler/src/build.d tool directly now (see docs), or build compiler and druntime in one step via the top-level Makefile in the repo root, e.g., for an optimized build using an LDC host compiler: make -jN HOST_DMD=ldmd2 ENABLE_RELEASE=1 ENABLE_LTO=1

    The top-level Makefile has been renamed from posix.mak to Makefile (with a deprecated posix.mak forwarder). The semantics of some targets have slightly changed, e.g., druntime is included in the test, install and clean targets now.

    The legacy src/posix.mak file still exists, but forwards to the top-level Makefile. So e.g. the default all target now includes druntime too, not just the compiler.

    Top-level win{32,64}.mak and legacy src/win{32,64}.mak files (for DigitalMars make) have been removed altogether. The generic top-level Makefile works on Windows too - with a GNU make (and a git installation providing bash and GNU tools).

    Long-deprecated compiler/test/Makefile has also been removed; use compiler/test/run.d directly instead (see docs).

  3. Unrecognized pragmas are no longer an error, but instead simply ignored

    Previously, unrecognized pragmas would issue a hard error unless you used the -ignore dmd switch. Now, they are always ignored and the -ignore dmd switch is ignored.

  4. Added @standalone for module constructors

    When two modules import each other and both have module constructors, druntime would throw an error because it can't determine which to run first.

    This could be circumvented by using pragma(crt_constructor) instead, but in C runtime constructors, druntime isn't initialized. Therefore the Garbage Collector can't be used in such constructors.

    @standalone is a new attribute that can be used to mark module constructors that run after druntime has been initialized, but do not depend on any other module constructors being run before it, so it will not cause a cyclic dependency error. It must be imported from core.attribute.

    The compiler doesn't verify that the module constructor truly doesn't depend on other variables being initialized, so it must be enforced manually. Because of this, they must be marked @system or @trusted.

    import core.attribute : standalone;
    immutable int* x;
    @standalone @system shared static this()
        x = new int(10);
    void main()
        assert(*x == 10);

    If possible, prefer to solve cyclic dependency errors by putting the offending module constructors into their own smaller modules instead of using @standalone.

  5. _d_newarray{mTX,miTX,OpT} are converted to a single template: _d_newarraymTX

    The template _d_newarraymTX now uses DBI to check what type of initialiser is required by the type of the elements in the array. Thus it replaces both _d_newarraymTX and _d_newarraymiTX.

    _d_newarrayOpT was the generic implementation of both of the above hooks. It first allocated the "outer" arrays as pointer arrays and then it called either _d_newarrayT or _d_newarrayiT, to allocate initialise the "inner" 1-dimensional arrays accordingly. Now this is no longer needed due to the merge between _d_newarraymTX and _d_newarraymiTX.

    Now the compiler performs the following lowering:

    S[][] s = new S[][](2, 3)
    // is now lowered to:
    S[] s = _d_newarraymTX!(S[][], S)([2, 3]);

    This change adds the new template to

Runtime changes

  1. Using an invalid MemoryOrder for core.atomic operations are now rejected at compile time

    The following core.atomic functions have become more restrictive:

    1. atomicLoad and atomicStore now reject being instantiated with the
    argument MemoryOrder.acq_rel. Previously atomicLoad and atomicStore only rejected MemoryOrder.rel and MemoryOrder.acq respectively.

    In most cases, code that previously used MemoryOrder.acq_rel should switch to use MemoryOrder.seq instead.

    // Error:
    atomicStore!(MemoryOrder.acq_rel)(dest, value);
    // Corrective action:
    atomicStore!(MemoryOrder.seq)(dest, value);
    // Or:
    atomicStore(dest, value);

    1. atomicExchange now rejects being instantiated with the argument

    In most cases, code that previously used MemoryOrder.acq should switch to use MemoryOrder.seq instead.

    // Error:
    atomicExchange!(MemoryOrder.acq)(dest, value);
    // Corrective action:
    atomicExchange!(MemoryOrder.seq)(dest, value);
    // Or:
    atomicExchange(dest, value);

    1. atomicCompareExchangeWeak and atomicCompareExchangeStrong now reject
    being instantiated when the second fail argument is MemoryOrder.rel or MemoryOrder.acq_rel.

    In most cases, code that previously used either of these should switch to use MemoryOrder.raw instead.

    // Error:
    atomicExchangeWeak!(MemoryOrder.rel, MemoryOrder.rel)(dest, compare, value);
    atomicExchangeWeakNoResult!(MemoryOrder.acq_rel, MemoryOrder.acq_rel)(dest, compare, value);
    atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.rel)(dest, compare, value);
    atomicExchangeStrongNoResult!(MemoryOrder.seq, MemoryOrder.acq_rel)(dest, compare, value);
    // Corrective action:
    atomicExchangeWeak!(MemoryOrder.rel, MemoryOrder.raw)(dest, compare, value);
    atomicExchangeWeakNoResult!(MemoryOrder.acq_rel, MemoryOrder.raw)(dest, compare, value);
    atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.raw)(dest, compare, value);
    atomicExchangeStrongNoResult!(MemoryOrder.seq, MemoryOrder.raw)(dest, compare, value);

    1. atomicCompareExchangeWeak and atomicCompareExchangeStrong additionally
    now reject being instantiated when the second fail argument has a greater value than its first succ argument.

    In most cases, code that violates this contract should use the same MemoryOrder for both succ and fail arguments.

    // Error:
    atomicExchangeWeak!(MemoryOrder.raw)(dest, compare, value);
    atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.seq)(dest, compare, value);
    // Corrective action:
    atomicExchangeWeak!(MemoryOrder.raw, MemoryOrder.raw)(dest, compare, value);
    atomicExchangeStrong!(MemoryOrder.acq, MemoryOrder.acq)(dest, compare, value);
  2. Makefiles cleanup for druntime

    The {posix,win32,win64}.mak Makefiles have been merged to a generic Makefile (including the ones in druntime/test/). posix.mak is kept as a deprecated forwarder for now.

    On Windows, you can/need to use the generic Makefile too - with a GNU make (and a git installation providing bash and GNU tools). Windows devs can finally exploit parallelism via -j! You may download a prebuilt zipped .exe from

  3. New addition of the C stdatomic header implemented in D

    The goal of this module is to assist in porting efforts for code from C to D and to give as close as possible same code generation as the system C compiler counterpart.

    If you do not care about code generation quality should the aliases to the function names not exist, you may append _impl to get at the implementation.

    If the code generation provided by a given function is not on-par to the system C compiler and it matters to your use case, please report it as a bug.

Library changes

  1. isForwardRange now takes an optional element type.

    isForwardRange now has an optional 2nd template parameter that defaults to void. If not void, it only evaluates to true if the range's element type is the same type as this extra argument, modulo const. For instance, isForwardRange!(int[], const(int)) is true, but isForwardRange!(int[], string) is false.

  2. Makefiles cleanup

    The {posix,win32,win64}.mak Makefiles have been merged to a generic Makefile. posix.mak is kept as a deprecated forwarder for now.

    On Windows, you can/need to use the generic Makefile too - with a GNU make (and a git installation providing bash and GNU tools). Windows devs can finally exploit parallelism via -j! You may download a prebuilt zipped .exe from

List of all bug fixes and enhancements in D 2.107.0:

DMD Compiler regression fixes

  1. Bugzilla 24266: ImportC: struct initializer entry gets ignored
  2. Bugzilla 24274: [REG master] ImportC: unrecognized C initializer with array in struct
  3. Bugzilla 24295: [betterC] ICE with new int[]
  4. Bugzilla 24301: [REG 2.100] Misleading error message when passing non-copyable struct by value in @safe code
  5. Bugzilla 24338: Cannot concatenate dynamic arrays of enum type with static array base type

DMD Compiler bug fixes

  1. Bugzilla 16357: cast(T[])[x] casts x to T instead of [x] to T[]
  2. Bugzilla 20339: isPOD returns true if sizeof is accessed inside struct declaration
  3. Bugzilla 20369: shadowed variable in foreach loop always considered "foreach variable"
  4. Bugzilla 22216: Incomplete/incorrect error message for mutability overloads
  5. Bugzilla 22905: gdb backtrace contains wrong location
  6. Bugzilla 23411: ImportC: undefined identifier __builtin_nanf
  7. Bugzilla 23713: compilable/testcstuff1.c:206:1: error: static assertion failed: sizeof(u'a') == 4
  8. Bugzilla 23714: compilable/testcstuff1.c:213:1: error: static assertion failed: u'ab' == 0x610062
  9. Bugzilla 23972: class identity check is broken
  10. Bugzilla 24031: ImportC: rejects nested C initializers
  11. Bugzilla 24094: importC __declspec not working in front of declaration statement
  12. Bugzilla 24200: ImportC: .di file collected macro conflicts with Special Token
  13. Bugzilla 24224: __traits(initSymbol) treats aggregate-derived enum as base type
  14. Bugzilla 24248: const constructor call with mutable target gives wrong error message
  15. Bugzilla 24252: ci: Error: error writing file 'compilable\testcstuff3_0.obj'
  16. Bugzilla 24264: ImportC: inliner trips on _Bool return
  17. Bugzilla 24276: ImportC: typedef aliases not emitted correctly in .di files
  18. Bugzilla 24280: ImportC: forward reference error when compiling multiple files
  19. Bugzilla 24281: Segfault with missing field after named argument
  20. Bugzilla 24283: [SIMD][CODEGEN] Bad codegen with and not + AVX2 registers
  21. Bugzilla 24292: Struct with destructor wrongly returned in register
  22. Bugzilla 24303: anonymous struct problems when typedef'd in separate C files
  23. Bugzilla 24304: __uint16_t, __uint32_t, __uint64_t are not recognized
  24. Bugzilla 24306: ImportC: same name structs in separate C files interfere when compiled together
  25. Bugzilla 24309: Memory allocation failed on Azure pipeline
  26. Bugzilla 24311: Named enum with AA base type causes ICE
  27. Bugzilla 24319: OpenBSD: Use correct type for file_time
  28. Bugzilla 24326: ImportC: segfault on nameless enum translation with -H
  29. Bugzilla 24340: Invalid export directives generated

DMD Compiler enhancements

  1. Bugzilla 14387: Disallow string literals as assert conditions
  2. Bugzilla 23629: importC: Need to support code coverage analysis
  3. Bugzilla 24069: ImportC does not parse function pointer as parameter without name
  4. Bugzilla 24125: ImportC: vector type initializer not understood
  5. Bugzilla 24155: ImportC: accept C23 default initializers
  6. Bugzilla 24206: Can't alias a function type that returns a type with a TypeSuffix
  7. Bugzilla 24238: Confusing "not an lvalue"error messages
  8. Bugzilla 24247: Improve constructor not callable using $modifier object error
  9. Bugzilla 24294: ImportC: unrecognized command line option -Wno-builtin-macro-redefined with gcc
  10. Bugzilla 24297: ImportC incompatible with glibc _FORTIFY_SOURCE

Phobos regression fixes

  1. Bugzilla 24243: Can't format chain(filter, filter)

Phobos bug fixes

  1. Bugzilla 24151: std.container.array: Array!string("") does not compile
  2. Bugzilla 24215: std.traits.isBasicType!Enum should be false
  3. Bugzilla 24278: std.math.abs promotes unsigned argument to 32 bits
  4. Bugzilla 24342: T[][].until(T[]) breaks if sentinel is longer than 1.

Phobos enhancements

  1. Bugzilla 11111: std.algorithm.canFind should support Needles...
  2. Bugzilla 24075: Can't use toChars with ushort or ubyte

Druntime bug fixes

  1. Bugzilla 4071: Missing support to share memory and objects between DLLs and executable
  2. Bugzilla 24272: operations.arrayOp is forced @nogc nothrow pure
  3. Bugzilla 24298: cpp_delete should check for null

Druntime enhancements

  1. Bugzilla 20332: associative array clear function should be @safe bug fixes

  1. Bugzilla 23712: ImportC: Unclear documentation of what type is inferred from integer literals (type of 9223372036854775808 is undefined)
  2. Bugzilla 24239: tests on CircleCI run out of memory
  3. Bugzilla 24241: Spec disallows missing default arguments enhancements

  1. Bugzilla 24176: Parameters of opApply delegate don't have to be ref
  2. Bugzilla 24177: Array literal can implicitly convert to an expected type
  3. Bugzilla 24210: Function types are not documented

Contributors to this release (37)

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

previous version: 2.106.1 – next version: 2.107.1