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

previous version: 2.097.2

Download D 2.098.0 Beta
to be released Sep 15, 2021

2.098.0 comes with 8 major changes and 135 fixed Bugzilla issues. A huge thanks goes to the 62 contributors who made 2.098.0 possible.

List of all bug fixes and enhancements in D 2.098.0.

Compiler changes

  1. Using the syntax (args) => {} now triggers a deprecation message

    Newcomers from languages with built-in delegates (such as JavaScript and C#) would often use (args) => { /* body */ } for delegate/function literals.

    However, in D, this syntax results in a delegate that returns a delegate, without any other side effects. This may trigger hard-to-debug bugs, therefore it is now deprecated.

    If a delegate returning a delegate is indeed the intended usage, use either (args) { return () => /* body */; } or (args) => () { /* body */ }.

  2. Improvements for the C++ header generation

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

    • Declarations from template mixins are emitted into the instantation context
    • (Superclass) methods aliases are emitted as using ... instead of typedef ...
    • extern(D) symbols are no longer emitted by accident in certain situations
    • extern(D) structs and classes are emitted if referenced by an exported symbol
    • Symbols referenced from template declarations are emitted before their first use
    • Forward declarations consistently include template<...>
    • extern(C++, class), extern(C++, struct) affects forward declarations
    • Types used in reference parameters are forward declared if possible
    • Renamed or local imports are emitted as using ... when possible
    • Complex types are emitted as _Complex.
    • Declarations are emitted before the first member access
    • Global variables with invalid names in C++ are omitted
    • Initializers of union variables/parameters omit non-active members
    • Typecasts are emitted as C style, not D's cast(...) ...
    • Structs are always tagged as final because D disallows struct inheritance
    • No longer asserts for declarations using noreturn
    • Symbol names always include template parameters and enclosing declarations when required
    • Properly emits (static / enum) members of templated aggregates
    • Properly emits static arrays in template declarations
    • No longer omits the parent aggregate when referencing __gshared variables
    • No longer uses D syntax for expressions nested in unary / binary expressions
    • Does not emit public:, ... inside of anonymous structs/unions
    • Does not emit typedef for aliases to declaration symbols

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

  3. Using a mutable variable as a switch case now triggers an error

    Variables that are const or immutable can be used as switch cases even if they are initialized at run-time, but using variables that are mutable has been deprecated since dmd 2.073.2. This deprecation has now been turned into an error:

    void foo(int s, int x, const int y, immutable int z) {
        switch (s) {
            case x: // error
            case y: // allowed
            case z: // allowed

    It is advised to only use compile-time known values in case statements, because the presence of any run-time variable (even a const or immutable one) results in the entire switch being lowered to a series of if-else statements before code generation, instead of an efficient jump table. Prefer regular if-statements for comparing pairs of run-time known variables.

  4. Class allocators have been removed from the language

    Class allocators have been deprecated since v2.080.0.

    class C
        new(size_t size)
            return malloc(size);

    Starting with this release all class allocators not annotated with @disable will result in a compilation error. As the grammar will also be changing, there are new deprecation messages for the old-style allocator syntax, which accepted a non-empty parameter list and function body.

    class C
        @disable new(size_t size)   // Deprecation: non-empty parameter list
            return malloc(size);    // Deprecation: function definition

    Example of corrective action:

    class C
        @disable new();

    See the deprecated features page for more information.

Runtime changes

  1. A concurrent GC for Posix systems

    For Posix systems that support the fork() function (or the clone() on linux systems), the conservative/precise GC can be made concurrent by enabling the 'fork' GC options in the usual ways, e.g. by adding --DRT-gcopt=fork:1 to the command line or by embedding

    extern(C) __gshared string[] rt_options = [ "gcopt=fork:1" ];

    into your linked binary (see ../spec/garbage.html#gc_config).

    The application continues execution and new memory is allocated from the system while the forked process is marking heap objects. Parallel marking is disabled for the forked process so it only uses a single thread for minimal impact on the concurrent execution of the application.

    This reduces "stop the world" time at the cost of needing more memory and page-protection overhead when writing to memory currently being scanned.

  2. Improve POSIX imports

    The lwpid_t symbol was added to core/sys/linux/sys/procfs.d. The O_CLOEXEC symbol was added to core/sys/posix/fcntl.d.

Library changes

  1. New function isValidCharacter in std.utf

    A new function isValidCharacter has been added to std.utf. It can be used to check if a single character forms a valid code point. For example the char 0x80 is not a valid code point, because it can only be used in trailing characters of UTF8 sequences, whereas the wchar ä is a valid character:

    assert(!isValidCharacter(cast(char) 0x80));

Dub changes

  1. Added support for environment variables to use compilation and run(or test) option to the dub settings file and dub.json/dub.sdl.

    The following items have been added to the dub setting file: defaultEnvironments, defaultBuildEnvironments, defaultRunEnvironments, defaultPreGenerateEnvironments, defaultPostGenerateEnvironments, defaultPreBuildEnvironments, defaultPostBuildEnvironments, defaultPreRunEnvironments, defaultPostRunEnvironments. They are used when there are no project-specific settings.

        "defaultEnvironments": {
            "VAR": "Foo"

    The following items are available in each project-specific setting: environments, buildEnvironments, runEnvironments, preGenerateEnvironments, postGenerateEnvironments, preBuildEnvironments, postBuildEnvironments, preRunEnvironments, postRunEnvironments.

    In JSON

        "environments": {
            "VAR": "Foo"

    In SDL

    environments "VAR" "Foo"

List of all bug fixes and enhancements in D 2.098.0:

DMD Compiler regression fixes

  1. Bugzilla 21238: -deps considers only the first instantiation site of a template for dependencies
  2. Bugzilla 22035: [REG 2.097][ICE] Segmentation fault parsing invalid case statement
  3. Bugzilla 22054: Referencing a fwd-declared field results in many error messages
  4. Bugzilla 22075: [Reg 2.068] "AA key type S should have 'size_t toHash() const nothrow @safe' if opEquals defined" is not triggered if any field of S has its own 'alias this'
  5. Bugzilla 22086: importC: RangeError@src/dmd/dscope.d(469): Range violation
  6. Bugzilla 22118: Const union causes false multiple-initialization error in constructor
  7. Bugzilla 22121: [REG 2.097][ICE] Segmentation fault in in dmd.dsymbol.ScopeDsymbol.addAccessiblePackage
  8. Bugzilla 22122: [REG 2.097][ICE] Segmentation fault in in dmd.access.hasPackageAccess
  9. Bugzilla 22196: importC: Error: found const when expecting )in __attribute__
  10. Bugzilla 22214: Regression 2.097.0: __traits(compiles) doesn't notice invalid getMember that yields type
  11. Bugzilla 22224: [REG 2.097.0] compiler segfaults with -profile
  12. Bugzilla 22228: [CTFE] taking address of immutable in frame function causes ICE on Unix platforms

DMD Compiler bug fixes

  1. Bugzilla 13165: Using -profile does extra control flow analysis, leading to spurious statement is not reachable warning
  2. Bugzilla 14064: Error message about @ attributes incomplete.
  3. Bugzilla 15631: gdb: Parent's scope not considered for symbol lookup
  4. Bugzilla 16274: The curses of debugging: short argument passed in 16-bit register, against ABI
  5. Bugzilla 17041: foreach-ref can't use to static array's AliasSeq
  6. Bugzilla 20150: -dip1000 defeated by pure
  7. Bugzilla 20245: DIP1000: Should infer scope when taking address of ref
  8. Bugzilla 21209: scope attribute inference with does not work well with foreach
  9. Bugzilla 21868: DIP1000 doesn't catch pointer to struct temporary
  10. Bugzilla 21905: case of IFTI failure when combining ref, and alias this on a static instance
  11. Bugzilla 21928: Wrong location for "array literal in @nogc function main may cause GC allocation" error
  12. Bugzilla 21931: importC: 'alias time_t = time_t;' cannot alias itself, use a qualified name to create an overload set
  13. Bugzilla 21932: importC: enum 'ENUM' conflicts with enum 'ENUM'
  14. Bugzilla 21933: importC: struct parameters: AssertError@src/dmd/typesem.d(1890): Assertion failure
  15. Bugzilla 21934: importC: Support asm labels to specify the assembler name to use for a C symbol
  16. Bugzilla 21937: importC: Support parsing __attribute specifiers
  17. Bugzilla 21939: Duplicate error messages for wrong aggregate in 'static foreach'
  18. Bugzilla 21942: importC: Support parsing __inline__ keyword
  19. Bugzilla 21944: importC: Support parsing # line marker directive extensions
  20. Bugzilla 21945: importC AssertError@src/dmd/dsymbolsem.d(4787): Assertion failure
  21. Bugzilla 21946: importC: Support parsing __extension__ keyword
  22. Bugzilla 21948: importC: Support declaring local variables of typedef types
  23. Bugzilla 21949: noreturn doesn't follow covariance rules
  24. Bugzilla 21962: importC: Empty enums are accepted as valid code
  25. Bugzilla 21963: importC: Support declaring union types
  26. Bugzilla 21965: importC: Anonymous top-level struct or union triggers AssertError@dsymbolsem.d(4787)
  27. Bugzilla 21967: importC: Error function without 'this' cannot be 'const'
  28. Bugzilla 21968: importC: struct fields: AssertError@src/dmd/typesem.d(1890): Assertion failure
  29. Bugzilla 21970: importC: Error: variable extern symbols cannot have initializers
  30. Bugzilla 21973: importC: AssertError@src/dmd/dsymbolsem.d(4307): Assertion failure
  31. Bugzilla 21976: importC: does not distinguish between cast-expression and unary-expression correctly
  32. Bugzilla 21977: importC: Global declarations are thread-local by default
  33. Bugzilla 21982: importC: Error: variable no definition of struct
  34. Bugzilla 21985: "goto" errors with unexistent label report wrong/misleading line
  35. Bugzilla 21992: importC: Error: variable is used as a type
  36. Bugzilla 21994: (char*)"string" fails to compile
  37. Bugzilla 22005: ICE: Segmentation fault with static foreach and -betterC
  38. Bugzilla 22006: static foreach and foreach over tuple doesn't work on 16-bit
  39. Bugzilla 22007: static foreach: cannot implicitly convert expression Tuple4(0LU, 1) of type Tuple4 to int
  40. Bugzilla 22019: case 1,: allowed by grammar but not DMD
  41. Bugzilla 22028: importC: Parser accepts initializers for struct members
  42. Bugzilla 22029: importC: Parser accepts storage-class specifiers for fields
  43. Bugzilla 22030: importC: Wrong error with bad declarator
  44. Bugzilla 22032: importC: infinite loop: illegal combination of type specifiers
  45. Bugzilla 22053: catch { not rejected while in a template
  46. Bugzilla 22060: importC: Multiple forward declarations result in error struct conflicts with struct
  47. Bugzilla 22063: importC: Error: undefined identifier 'var' with pointer-to-typedef type
  48. Bugzilla 22066: importC: Error: expression expected, not ';' using (postfix-expression)++
  49. Bugzilla 22067: importC: cast-expression accepted as lvalue in assignment-expression
  50. Bugzilla 22068: importC: cast-expression accepted as lvalue in unary-expression
  51. Bugzilla 22069: importC: Error: found '&' instead of statement
  52. Bugzilla 22070: importC: Error: string literal is not an lvalue
  53. Bugzilla 22071: importC: Error: struct literal is not an lvalue
  54. Bugzilla 22073: importC: Error: found '.' when expecting ';' following compound literal
  55. Bugzilla 22079: importC: Error: '=', ';' or ',' expected taking sizeof compound literal
  56. Bugzilla 22080: ImportC: Error: cannot implicitly convert expression of type 'extern(C) function' to 'function'
  57. Bugzilla 22088: ImportC: C11 6.3 semantics on implicit conversions is not implemented
  58. Bugzilla 22102: importC: Error: function is used as a type
  59. Bugzilla 22103: importC: Parser accepts wrong syntax for array declarators
  60. Bugzilla 22106: importC: Error: variable 'var' no definition of struct 'type'
  61. Bugzilla 22126: -checkaction=context should not print overlapped struct members
  62. Bugzilla 22149: TypeInfo_Struct names aren't unique, leading to botched equality semantics
  63. Bugzilla 22150: TypeInfo_Class names aren't unique, leading to botched equality semantics
  64. Bugzilla 22160: importC: Error: redeclaring module test as struct test
  65. Bugzilla 22180: .alignof not working for globals
  66. Bugzilla 22182: importC: Error: expression expected, not ) when casting pointer with redundant parens.
  67. Bugzilla 22209: NRVO variable detection ignoring alias this conversion => segfaults
  68. Bugzilla 22252: ImportC: Array, Function parameter types should be converted to pointers
  69. Bugzilla 22262: importC: Error: incompatible types for '(buf) is (0)': 'ubyte*' and 'int'
  70. Bugzilla 22274: importC: [ICE]: 4 identifiers does not match 3 declarations using K&R syntax

DMD Compiler enhancements

  1. Bugzilla 15889: Array bounds check should report index and length
  2. Bugzilla 16001: Lambda syntax: forbid use with FunctionLiteralBody: (x) => {assert(x);}
  3. Bugzilla 16689: Errors in instantiated mixin templates should show instantiation point
  4. Bugzilla 17400: put a new line before "candidates are:" in error messages
  5. Bugzilla 18907: Support cross-compiling
  6. Bugzilla 21885: Bad diagnostic: struct is not copyable because it is annotated @disable
  7. Bugzilla 21997: CTFE should allow function pointer casts with different attributes
  8. Bugzilla 22038: final switch error message should report all missing enum members
  9. Bugzilla 22115: Optimize if (s.a == 3 ? s : null) to if (s.a == 3)
  10. Bugzilla 22138: foreach cannot declare the loop variables as scope
  11. Bugzilla 22227: if (scope f = x()) and while (scope f = x()) do not parse

Phobos regression fixes

  1. Bugzilla 21920: [REG master] Error: auto can only be used as part of auto ref for template function parameters

Phobos bug fixes

  1. Bugzilla 19727: std.algorithm.endsWith fails to compile while startsWith succeeds
  2. Bugzilla 20393: formattedRead accepts input, that should be rejected
  3. Bugzilla 20937: std.range.array of a lengthless range with indirection is not @safe
  4. Bugzilla 21916: Error message is obfuscated when using wrong format specifier at compile-time
  5. Bugzilla 22001: Equality of std.conv.toChars() results for radix 10 depends on uninitialized bytes
  6. Bugzilla 22077: std.sumtype support for copy constructors is incomplete
  7. Bugzilla 22101: Nullable.get(fallback) cannot be used with non-@safe/pure/nothrow types
  8. Bugzilla 22110: isCallable fails for template opCall without any templated argument
  9. Bugzilla 22140: FunctionTypeOf fails for template opCall without any templated argument
  10. Bugzilla 22146: std.algorithm.searching.findAdjacent() can fall off end of function
  11. Bugzilla 22222: Custom unittest runner on phobos fails due to segfault on fork() exiting

Phobos enhancements

  1. Bugzilla 16210: std.utf.byUTF can be made into a bidirectional range
  2. Bugzilla 16218: Windows std.file.readImpl should be marked @system
  3. Bugzilla 18632: enable use of fromStringz with char[n]
  4. Bugzilla 20665: std.concurrency.spawn should document not working with delegates
  5. Bugzilla 21926: Allow leading zeros in std.conv.octal
  6. Bugzilla 22100: Support chained assignment of Nullable
  7. Bugzilla 22225: SumType: Some assignments should be able to execute in safe code

Druntime bug fixes

  1. Bugzilla 9799: Missing aliases and enums in druntime imports
  2. Bugzilla 14439: aa's keys, values not usable in @safe context
  3. Bugzilla 21550: core.memory.__delete does not actually work
  4. Bugzilla 21983: dup leaves a partially constructed array if postblit/copy ctor throws
  5. Bugzilla 21996: -checkaction=context triggers InvalidMemoryOperationError in finalizer
  6. Bugzilla 22024: hashOf does not work on enum types whose base type is a SIMD vector
  7. Bugzilla 22026: checkaction=context: Exception thrown by toString hides assertion failures
  8. Bugzilla 22076: hashOf(S) can segfault if S.toHash is forwarded via 'alias this' to a receiver which may be null
  9. Bugzilla 22081: DWARF v5 support is utterly broken - 'illegal instruction' when throwing exceptions
  10. Bugzilla 22085: checkaction=context doesn't support extern(C++) classes
  11. Bugzilla 22107: [scope][dip1000] Can't .dup an array of structs with impure copy constructor
  12. Bugzilla 22143: Throwable ctor doesn't increment chained exception's ref count
  13. Bugzilla 22218: Dynamic casts across binary boundaries can easily fail

Druntime enhancements

  1. Bugzilla 22169: Mark as pure core.sys.posix.string: memccpy, stpcpy, stpncpy, strnlen bug fixes

  1. Bugzilla 3345: Static and nonstatic methods with the same name should be allowed
  2. Bugzilla 20557: Spec does not allow StringPostfix after DelimitedString or TokenString while implementation does
  3. Bugzilla 21125: Typo in std.range.refRange documentation for opIndex
  4. Bugzilla 21906: obscure sentence in the introduction to phases of compilation
  5. Bugzilla 21935: Broken Link in Lazy Evaluation Article
  6. Bugzilla 22229: Struct initialization via constructor missing from language spec enhancements

  1. Bugzilla 21495: File.readf documentation does not state what what is returned.
  2. Bugzilla 21600: Regex.namedCaptures is undocumented

Installer bug fixes

  1. Bugzilla 21488: Bundled 32-bit dlang tools (ddemangle, dustmite, rdmd) segfault on startup

Contributors to this release (62)

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

previous version: 2.097.2