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

previous version: 2.105.3 – next version: 2.106.1

Download D 2.106.0
released Dec 01, 2023

2.106.0 comes with 17 major changes and 65 fixed Bugzilla issues. A huge thanks goes to the 33 contributors who made 2.106.0 possible.

List of all bug fixes and enhancements in D 2.106.0.

Compiler changes

  1. Catch clause must take only const or mutable exceptions

    In 2.104, throwing qualified types was deprecated.

    It is also unsafe to catch an exception as immutable, inout or shared. This is because the exception may still be accessible through another mutable or non-shared reference. Catching an exception with those qualifiers is now deprecated.

    auto e = new Exception("first");
    try {
            throw e;
    } catch(immutable Exception ie) { // now an error
            e.msg = "second";
            assert(ie.msg == "first"); // would fail
  2. Improvements for the C++ header generation

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

    • Static variables used in a default argument context are now emitted using their fully qualified name.

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

  3. A function with enum storage class is now deprecated, not an error

    The error was introduced in 2.105.0.

  4. Add -nothrow Switch to Compiler

    dmd itself (and presumably others) do not throw Exceptions, preferring other methods for dealing with errors. There is a cost, however, in supporting Exceptions even when they are never thrown. The cost is in adding stack unwinders for things like RAII objects, and preventing numerous optimizations across try-catch boundaries.

    Adding nothrow to all the code in a project turns out to be an inordinate amount of work if the program is large. Putting nothrow: at the top of the module doesn't influence the status for member functions in a class or struct, the nothrow: will have to be repeated for each class/struct.

    Adding the -nothrow switch to the compiler causes the stack unwinders to not be added and enables the optimizations. This capability is already there for -betterC code, this would just enable it for regular D code.

    The switch does not affect semantic analysis, just the code generation. Name mangling is not affected.

    The switch is useful for determining what effect exception handling has on an executable's size and performance in non-throwing code.

  5. Added support for Intel CET (Control-flow Enforcement Technology) IBT (Indirect Branch Tracking) protection

    CET is a technology that is useful for preventing an attacker from redirecting a program's control flow, specifically IBT prevents an attacker from causing an indirect branch to go to an unintended place.

    Intel IBT expects the compiler to emit special instructions (endbr32 and endbr64) which in older processors that do not support IBT are equivalent to nop instructions, consequently a program compiled with active IBT will be compatible on any x86 processor and the protection will be opportunistically active on supported processors.

    To enable Intel IBT protection in DMD you need to pass the -fIBT flag to the compiler, consequently the compiler will manage the emission of instructions for IBT by itself. Be careful when using inline assembly, the compiler will not automatically handle IBT inside an inline assembly.

    To find out within a D program whether IBT has been activated or not use the traits getTargetInfo as follows:

    // IBT active
    static assert(__traits(getTargetInfo, "CET") == 1);  // CET == 1 if IBT is active
    // IBT not active
    static assert(__traits(getTargetInfo, "CET") == 0);  // CET == 0 if IBT is not active
  6. Creating a scope class instance with a non-scope constructor is @system only with DIP1000

    The fix for issue 23145 broke existing code, so it's put behind -preview=DIP1000 now, just like other scope related errors.

  7. Global const variables can no longer be initialized from a non-shared static constructor

    Just like immutable data, global const data is not placed in Thread Local Storage (TLS), so initializing it in a thread-local static constructor allows you to violate const: see issue 24056 for details. Doing this will now result in a deprecation:

    int x;
    const int y;
    immutable int z;
    static this()
        x = 1;
        y = 2; // Deprecation: cannot modify const variable
        z = 3; // Error: cannot modify immutable variable (same as before)

    As a corrective action, move the initialization to a shared static constructor:

    const int y;
    shared static this()
        y = 4; // OK
  8. Global variables can now be initialized with Associative Arrays

    Formerly, module constructors or enum had to be used to initialize global variables with Associtive Arrays. By internally lowering to Steven Schveighoffer's newaa struct implementation, Associative Arrays can now be used directly.

    immutable string[string] table = ["key": "value"];
    void main()
        assert(table["key"] == "value");

    When the key/value types have toHash, opEquals or ~this defined, they must be callable at compile time. An if (!__ctfe) branch can be used to make a destructor only run at run time. Future enhancements may obviate the need for this workaround.

  9. _d_newarray{U,T,iT} are converted to templates

    The template _d_newarrayT 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_newarrayT and _d_newarrayiT.

    _d_newarrayU is the generic implementation of both of the above hooks and just allocates the array. It hasn't been incorporated into _d_newarrayT because it is used by dup. Currently dup is still using the non-template _d_newarrayU. A future PR will update dup to use the new template.

    Now the compiler performs the following lowering:

    S[] s = new S[10]
    // is now lowered to:
    S[] s = _d_newarrayT!S(10);

    This change adds the new templates to In addition, it implements template __arrayClearPad, __arrayAlloc, __arrayStart and __setArrayAllocLength in core.internal.array.utils. __arrayClearPad and __arrayStart were also removed from rt.lifetime. The others can't be removed yet because they receive a TypeInfo argument and are called by other hooks in rt.lifetime.

Runtime changes

  1. 4 core.memory.GC functions have been marked @safe

    • GC.enable
    • GC.disable
    • GC.collect
    • GC.minimize

Library changes

  1. Undo etc.c.odbc deprecation and enable usage on non-Windows systems

    Previously, the etc.c.odbc bindings were deprecated and forwarded the versions of the bindings via public import. However, ODBC is supported on all major platforms and the machine translated MinGW bindings in have version(Windows) specified which results in being unable to use those bindings on non-Windows platforms. The bindings have been returned to etc.c.odbc, undeprecated, and support for non-Windows platforms enabled.

  2. isInputRange now takes an optional element type.

    isInputRange 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, isInputRange!(int[], const(int)) is true, but isInputRange!(int[], string) is false.

  3. Add Unshared to std.traits.

    Unshared is the shared equivalent of Unconst. It strips off the outer layer of shared from a type. e.g.

        static assert(Unshared!(shared int) == int);
        static assert(Unshared!(shared(int[])) == shared(int)[]);

    So, Unconst strips off the outer layer of const, immutable, and inout; Unshared strips off the outer layer of shared; and Unqual strips off all qualifiers from the outer layer of a type.

Dub changes

  1. Added --deep= switch to dub build

    By specifying this flag, you can now build all the dependencies of a staticLibrary. The default behavior is to only build the library located in the root directory of the dub configuration file. This allows better integration with other build systems which require the libraries to be built upfront.

    dub build --deep

    If a staticLibrary A depends on staticLibrary B, and the --deep flag is specified, dub will output both the A and B libraries.

  2. Added default-config, configs, default-build, builds data to dub describe

    • default-config will be a single string that is the --config configuration that DUB would pick when not provided any configuration such as in a simple dub build call
    • configs is a list of all available configurations (default generated application and/or library, or the manually specified ones in the recipe)
    • default-build will be a single string that is the --build build type that DUB would pick when not provided any (currently always "debug")
    • builds is a list of all available build types (built-in + custom defined)

  3. Dub init now has a select menu for package format and license

    When creating a package using dub init you are now prompted to select a license for the package.

  4. Added --recipe= switch to DUB

    You can now override which file is used as recipe, instead of the default dub.sdl and dub.json. This means you can define multiple dub.json files for local development, for example for special local-machine-only operations, and select which one to use over the CLI.

    dub build --recipe=custom-dub.json

    This can also be used to pick dub.sdl over dub.json, if both of them exist in the same directory. Although this is discouraged for interoperability with other DUB-supporting tools and general confusion for users. Both existing at the same time may also become an error when this switch is not specified in the future.

List of all bug fixes and enhancements in D 2.106.0:

DMD Compiler regression fixes

  1. Bugzilla 20655: [REG: 2.072] attribute inference accepts unsafe union access as @safe
  2. Bugzilla 24066: __traits(isAbstractClass) causes a segfault when passed an opaque class
  3. Bugzilla 24159: BetterC: appending to dynamic arrays no longer errors at compile time
  4. Bugzilla 24184: [REG 2.103] Segmentation fault accessing variable with align(N) > platform stack alignment

DMD Compiler bug fixes

  1. Bugzilla 8662: Better error for duplicate labels inside static foreach body
  2. Bugzilla 11455: Overriding template methods should raise a compile error
  3. Bugzilla 14835: Constant folding should not affect front end flow analysis
  4. Bugzilla 18578: First enum value assigned 0 instead of EnumBaseType.init
  5. Bugzilla 19460: C style cast error has wrong line number for functions
  6. Bugzilla 22682: pragma(mangle) does not work for nested functions
  7. Bugzilla 23103: static initialization of associative arrays is not implemented
  8. Bugzilla 23522: Error message when enum type is not integral and a value lacks an initializer
  9. Bugzilla 23733: Can't use template type parameter as type of alias parameter
  10. Bugzilla 24036: assert message in CTFE becomes ['m', 'e', 's', 's', 'a', 'g', 'e'][0..7] if produced using std.format.format
  11. Bugzilla 24051: Safety attrib inference of enum/immut/const decls inconsistent with mutable static variable decls
  12. Bugzilla 24054: return expression expected on noreturn function
  13. Bugzilla 24055: is(x == __parameters) does not work on function pointer/delegate types
  14. Bugzilla 24056: const uninitialized data at module scope is not in TLS
  15. Bugzilla 24065: __traits(getTargetInfo) causes a segfault when passed a non value
  16. Bugzilla 24070: Opaque struct with nested definition when taking pointer segfaults
  17. Bugzilla 24071: When enum has typedef integer constants do not have types determined correctly
  18. Bugzilla 24072: cast(__vector) array literal incorrectly triggers GC error
  19. Bugzilla 24105: Dip1000 C variadics not marked as scope should not accept scope arguments
  20. Bugzilla 24107: The error for exceeding the CTFE recursion limit bypasses speculative compilation.
  21. Bugzilla 24108: dmd -H and -X fail when given an importC module
  22. Bugzilla 24117: noreturn can be used as expression
  23. Bugzilla 24121: ImportC: typedef enum fails to compile when generating .di file
  24. Bugzilla 24129: ImportC: MS-Link cannot handle multiple COMDATs with the same name
  25. Bugzilla 24130: ImportC: Windows headers use inline asm with different syntax
  26. Bugzilla 24133: printf format checking of %n allows writing to const pointers
  27. Bugzilla 24154: ImportC: useless expression parsed as invalid variable declaration
  28. Bugzilla 24156: ImportC: Apple uses __signed as a keyword
  29. Bugzilla 24168: Corrupted if TLS values are passed in ref parameters when compiling with -fPIE
  30. Bugzilla 24174: [CTFE] goto within with statements & catch blocks cause a infinite loop
  31. Bugzilla 24181: reading double parameter from RCX rather than XMM1
  32. Bugzilla 24187: ImportC: _Float32 not defined
  33. Bugzilla 24193: Incorrect size of unions with bit fields
  34. Bugzilla 24199: ImportC: generated .di file uses struct keyword when referring to a type
  35. Bugzilla 24208: [DIP1000] Scope pointer can escape via non-scope parameter of pure nested function
  36. Bugzilla 24209: static aa initialization of static function variable ICE
  37. Bugzilla 24212: [DIP1000] Scope pointer can escape via non-scope parameter of pure virtual function
  38. Bugzilla 24213: [DIP1000] Scope pointer can escape via non-scope parameter of pure delegate
  39. Bugzilla 24257: ImportC: ICE on accessing last _Bool bitfield
  40. Bugzilla 24262: Assert error with bit fields

DMD Compiler enhancements

  1. Bugzilla 5445: DMD does not look for ".dmd.conf" in HOME dir
  2. Bugzilla 10532: Silence some unreachable statement warnings when in a static foreach
  3. Bugzilla 11070: Allow declaration statement in a switch expression
  4. Bugzilla 15752: Diagnostic: Better Error Message for Assigning Incorrect AA Empty Value
  5. Bugzilla 20522: Spurious statement unreachable warning caused by undefined variable
  6. Bugzilla 21520: dmd does not honor the NO_COLOR environment variable
  7. Bugzilla 21852: diagnostic: One-liner errors with formatted Loc should print context when -verrors=context
  8. Bugzilla 23958: ImportC: undefined identifier __builtin__sprintf_chk
  9. Bugzilla 24060: Improve "Cannot create instance of abstract class" error
  10. Bugzilla 24084: Add -nothrow Switch to Compiler
  11. Bugzilla 24173: ImportC: add Microsoft iNN integer literal suffixes

Phobos regression fixes

  1. Bugzilla 24267: [REG 2.106 beta] Grapheme cannot be used as an AA key

Phobos bug fixes

  1. Bugzilla 24049: string to enum conversion is not documented
  2. Bugzilla 24207: std.parallelism: AbstractTask private data is inadvertently available

Phobos enhancements

  1. Bugzilla 24082: add Int128.toString that supports std.format
  2. Bugzilla 24142: Allow casting Int128 to integral and floating types

Druntime bug fixes

  1. Bugzilla 24079: returns bad pointer
  2. Bugzilla 24123: More importc definitions are needed for macOS
  3. Bugzilla 24230: Infinite loop in core.cpuid.getCpuInfo0B in Solaris/x86 kernel zone bug fixes

  1. Bugzilla 3396: Compiler accepts call of superclass abstract method with no implementation enhancements

  1. Bugzilla 24012: [spec/cpp_interface] _d_dynamicArray generated by -HC not documented

Contributors to this release (33)

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

previous version: 2.105.3 – next version: 2.106.1