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
released Oct 10, 2021

2.098.0 comes with 17 major changes and 160 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. Add Alias Assignment

    This adds the ability for an alias declaration inside a template to be assigned a new value. For example, the recursive template:

    template staticMap(alias F, T...)
    {
        static if (T.length == 0)
            alias staticMap = AliasSym!();
        else
            alias staticMap = AliasSym!(F!(T[0]), staticMap!(T[0 .. T.length]));
    }
    

    can now be reworked into an iterative template:

    template staticMap(alias F, T...)
    {
        alias A = AliasSeq!();
        static foreach (t; T)
            A = AliasSeq!(A, F!t); // alias assignment here
        alias staticMap = A;
    }
    

    Using the iterative approach will eliminate the combinatorial explosion of recursive template instantiations, eliminating the associated high memory and runtime costs, as well as eliminating the issues with limits on the nesting depth of templates. It will eliminate the obtuse error messages generated when deep in recursion.

    The grammar:

    AliasAssign:
        Identifier = Type;
    

    is added to the expansion of DeclDef. The Identifier must resolve to a lexically preceding AliasDeclaration:

    alias Identifier = Type;
    

    where the Identifier's match, and both are members of the same TemplateDeclaration. Upon semantic processing, when the AliasAssign is encountered the Type in the AliasAssign replaces the Type from the corresponding AliasDeclaration or any previous matching AliasAssign.

    The AliasAssign grammar was previously rejected by the parser, so adding it should not break existing code.

  2. Accessing C Declarations From D Via ImportC Compiler

    One of D's best features is easy integration with C code. There's almost a one-to-one mapping between C and a subset of D code (known as DasBetterC). D and C code can call each other directly.

    But D cannot read C code directly. In particular, the interface to most C code comes in the form of a .h (or "header") file. To access the declarations in the .h file and make them available to D code, the C declarations in the .h file must somehow be translated into D. Although hand translating the .h files to D is not difficult, it is tedious, annoying, and definitely a barrier to using D with existing C code.

    Why can't the D compiler simply read the .h file and extract its declarations? Why doesn't it "just work"? D has had great success with integrating documentation generation into the language, as well as unit testing. Despite the existence of many documentation generators and testing frameworks, the simplicity of it being built in and "just working" is transformative.

    The C Preprocessor

    Is its own language that is completely distinct from the C language itself. It has its own grammar, its own tokens, and its own rules. The C compiler is not even aware of the existence of the preprocessor. (The two can be integrated, but that doesn't change the fact that the two semantically know nothing about each other.) The preprocessor is different enough from D that there's no hope of translating preprocessor directives to D in anything but the most superficial manner, any more than the preprocessor directives can be replaced with C.

    Previous Solutions

    htod by Walter Bright

    htod converts a C .h file to a D source file, suitable for importing into D code. htod is built from the front end of the Digital Mars C and C++ compiler. It works just like a C or C++ compiler except that its output is source code for a D module rather than object code.

    DStep by Jacob Carlborg

    DStep code

    DStep Article

    From the Article: "DStep is a tool for automatically generating D bindings for C and Objective-C libraries. This is implemented by processing C or Objective-C header files and outputting D modules. DStep uses the Clang compiler as a library (libclang) to process the header files."

    dpp by Átila Neves

    dpp code

    dpp Article

    From the Article: "dpp is a compiler wrapper that will parse a D source file with the .dpp extension and expand in place any #include directives it encounters, translating all of the C or C++ symbols to D, and then pass the result to a D compiler (DMD by default)."

    Like DStep, dpp relies on libclang.

    Introducing ImportC, an ISO C11 Compiler

    Here is the next step:

    • Forget about the C preprocessor.
    • Overlook C++.
    • Put a real ISO C11 compiler in the D front end.
    • Call it ImportC to distinguish this unique capability.

    In detail:

    1. Compile C code directly, but only C code that has already been run through
    the C preprocessor. To import stdio.h into a D program, the build script would be:

    gcc -E -P stdio.h >stdio.c

    and in the D source file:

    import stdio; // reads stdio.c and compiles it

    With gcc doing all the preprocessor work, it becomes 100% behavior compatible.

    1. A C compiler front end, stripped of its integrated preprocessor, is a simple
    beast. It could be compiled directly into dmd's internal data structure types.

    1. The D part of dmd will have no idea it originated as C code. It would be
    just another import. There is no change whatsoever to D.

    Using ImportC As A C Compiler

    Instead of importing C code, dmd can be used to compile C code like a standalone C compiler.

    Create the file hello.c:

    int printf(const char*, ...);
    
    int main()
    {
        printf("hello world\n");
    }
    

    Compile and run it:

    dmd hello.c
    ./hello
    hello world!
    

    For C code using C includes you can preprocess the C source with a C preprocessor. Create the file testcode.c:

    #include <stdint.h>
    
    uint32_t someCodeInC(uint32_t a, uint32_t b)
    {
        return a + b;
    }
    

    Preprocess the C code with the C preprocessor:

    gcc -E -P testcode.c >testcode.i
    

    Create D file d_main.d:

    import std.stdio;
    import testcode;
    
    void main()
    {
        writeln("Result of someCodeInC(3,4) = ", someCodeInC(3, 4) );
    }
    

    Compile and run it:

    dmd d_main.d testcode.i
    ./d_main
    Result of someCodeInC(3,4) = 7
    

    The '.i' file extension can be used instead of '.c'. This makes it clear, that preprocessed imtermediate C code is in use. The '.i' files can be created by some generator script or a Makefile.

    Implementation Details

    User Experience

    • Error messages are spare and utilitarian.

    • Recovering after encountering an error is not well developed.
    Only the first error message is likely to be on point.

    • Pretty-printing code is done in D syntax, not C. Also,
    differing precedence for Relational/Equality expressions.

    • No warnings are emitted. ImportC doesn't care about coding style,
    best practices or suspicious constructs. If ISO C says it's good, it passes.

    • If the ImportC code corrupts memory, overflows buffers, etc.,
    it will still compile. Use DasBetterC for a better way.

    • Symbolic debugging support is there.

    Variance From ISO C11

    • Doesn't have a C Preprocessor.
    The C code must be run through a preprocessor before it can be processed by ImportC. Incorporating this into your build system is advisable.

    • Tag symbols are part of the global symbol table, not the special tag
    symbol table like they are supposed to reside in.

    • Multiple chars in char literal are not supported.

    • _Atomic as type qualifier is ignored.

    • _Atomic as type specifier is ignored.

    • _Alignof is ignored.

    • _Generic is not implemented.

    • const is transitive, as in D. A pointer to a const pointer to a mutable
    value can be declared, but it'll be treated as a pointer to a const pointer to a const value.

    • { initializer-list } is not implemented.

    • ( type-name ) { initializer-list } is not implemented.

    • Complex numbers are not implemented.

    • Forward referencing works in ImportC. All global symbols are visible
    during semantic processing, not just the ones lexically prior to the piece of code it is working on.

    • Semantics applied after C parsing are D semantics, not C semantics,
    although they are very close. For example, implicitly converting an int to a char will pass C without complaint, but the D semantic pass will issue an error.

    Implementation Defined Behavior

    The C11 Standard allows for many instances of implementation defined behavior.

    • volatile, restrict, register, _Noreturn are accepted and ignored

    • char is unsigned

    • inline is ignored, as the D compiler inlines what it feels like inlining.

    • long double matches what the host C compiler does, which is not necessarily
    the same as D's real type.

    Extensions

    Using a D compiler for semantic processing offers many temptations to add in better D semantics. Inventing yet another new dialect of C is not the point of ImportC. However, some things are useful:

    • Compile Time Function Execution

    This works. It comes in handy for writing test cases for ImportC using _Static_assert. It also means that the D compiler can execute the ImportC functions in imports just like it can for D.

    Unimplemented Extensions

    • Much of C code makes use of extensions provided by the host C compiler.
    None of these are implemented.

    • Alternative keywords are not implemented. You can define the alternate keywords as macros to remove or replace them with standard keywords.

    #define __attribute __attribute__
    #define __asm       asm
    #define __asm__     asm
    #define __const     const
    #define __const__   const
    #define __inline    inline
    #define __inline__  inline
    #define __extension__
    
    #include <stdlib.h>
    

    Future Directions

    C Preprocessor

    Some means of incorporating this may be practical. For now, use cpp, warp or spp.

    Translation of C macros to D needs to be done, as htod, DStep and dpp all do this.

    ImportC++ ?

    No. Use dpp.

    ImportObjective-C ?

    No. Use DStep.

    Documentation

    More info on ImportC will be written on its page in the specification.

  3. 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 */ }.

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

  5. -preview=dtorfields is now enabled by default

    This preview ensures that partially constructed objects are properly destroyed when an exception is thrown inside of an constructor. It was introduced in 2.075 and is now enabled by default.

    Note that code may fail to compile if a constructor with strict attributes may call a less qualified destructor:

    struct Array
    {
        int[] _payload;
        ~this()
        {
            import core.stdc.stdlib : free;
            free(_payload.ptr);
        }
    }
    
    class Scanner
    {
        Array arr;
        this() @safe {} // Might call arr.~this()
    }
    

    Such code should either make the constructor nothrow s.t. the destructor will never be called, or adjust the field destructors.

    The compiler will only issue a deprectation for attribute violations caused by the inserted destructor call unless the -preview=dtorfields flag is explicitly specified.

  6. Add .min, .max, etc. properties for vector types.

    For integral vector types, add the .min and .max properties.

    For floating point vector types, add the .min, .max, .min_normal, .nan, .infinity, and .epsilon properties.

    The value of those properties is the value corresponsing to the vector element type broadcast to the vector type. I.e.:

    import core.simd;
    
    static assert(float4.max == cast(float4)float.max);
    
  7. 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
            default:
        }
    }
    

    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.

  8. Out of bounds array access now gives a better error message

    Errors resulting from bad indexing will now contain the length of the array, as well as the offending index for arr[bad], or offending indices arr[bad1 .. bad2] for bad slices.

    For example:

    void main()
    {
        int[] a = [1, 2, 3];
        int b = a[7];
    }
    

    Previously this would yield the following error when compiled and run:

    dmd -run main.d
    [email protected](4): Range violation
    ––––––––––
    ??:? _d_arrayboundsp [0x555765c167f9]
    ??:? _Dmain [0x555765c16752]
    

    It now yields:

    dmd -run main.d
    [email protected](4): index [7] exceeds array of length 3
    ––––––––––
    ??:? _d_arraybounds_indexp [0x5647250b980d]
    ??:? _Dmain [0x5647250b9751]
    

    Similarly, in case of out of bounds slice operations:

    void main()
    {
        int[] a = [1, 2, 3];
        int[] b = a[2 .. 4];
    }
    

    dmd -run main.d
    [email protected](4): slice [2 .. 4] extends past array of length 3
    ––––––––––
    ??:? _d_arraybounds_slicep [0x5647250b980d]
    ??:? _Dmain [0x5647250b9751]
    

    The error messages for an out of bounds slice copy (arr[a..b] = arr[c..d]) or indexing a non-existent key in an Associative Array (table["bad"]) have not been updated.

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

  10. Initialization of immutable global data from static this now triggers an error

    The following code has been deprecated since 2.087.0.

    module foo;
    immutable int bar;
    static this()
    {
        bar = 42;
    }
    

    This is problematic because module constructors (static this) run each time a thread is spawned, and immutable data is implicitly shared, which led to immutable value being overriden every time a new thread was spawned.

    The corrective action for any code that still does this is to use `shared static this over static this`, as the former is only run once per process.

  11. Add -target=<triple> for operating system, c, and c++ runtime cross compilation

    The command line switch -target=<triple> can be used to specify the target the compiler should produce code for. The format for <triple> is <arch>-[<vendor>-]<os>[-<cenv>[-<cppenv]]. Specific values of the specifiers are shown in the tables below.

    <arch>


    <arch> is an Architecture bitness, optionally followed by instruction set (which duplicates the functionality of the -mcpu flag)
    <arch>Architecture bitness
    x86_6464 bit
    x6464 bit
    x8632 bit
    x3264bit with 32 bit pointers

    subarch featuresequivalent -mcpu flag
    +sse2baseline
    +avxavx
    +avx2avx2

    The architecture and subarch features are concatenated, so x86_64+avx2 is 64bit with avx2 instructions.

    <vendor>


    <vendor> is always ignored, but supported for easier interoperability with other compilers that report and consume target triples.

    <os>


    <os> is the operating system specifier. It may be optionally followed by a version number as in darwin20.3.0 or freebsd12. For Freebsd, this sets the corresponding predefined version identifier, e.g. freebsd12 sets version(FreeBSD12). For other operating systems this is for easier interoperability with other compilers.

    <os>Operating system
    freestandingNo operating system
    darwinMacOS
    dragonflyDragonflyBSD
    freebsdFreeBSD
    openbsdOpenBSD
    linuxLinux
    solarisSolaris
    windowsWindows

    <cenv>


    <cenv> is the C runtime environment. This specifier is optional. For MacOS the C runtime environment is always assumed to be the system default.

    <cenv>C runtime environmentDefault for OS
    muslmusl-libc
    msvcMSVC runtimeWindows
    bionicAndriod libc
    digital_marsDigital Mars C runtime for Windows
    | glibc | GCC C runtime | linux | | newlib | Newlib Libc | | | uclibc | uclibc | |

    <cppenv>


    <cppenv> is the C++ runtime environment. This specifier is optional. If this specifier is present the <cenv> specifier must also be present.

    <cppenv>C++ runtime environmentDefault for OS
    clangLLVM C++ runtimeMacOS, FreeBSD, OpenBSD, DragonflyBSD
    gccGCC C++ runtimelinux
    msvcMSVC runtimeWindows
    digital_marsDigital Mars C++ runtime for Windows
    sunSun C++ runtimeSolaris

  12. Default initialization of union field that isn't the first member now triggers an error

    The following code has been deprecated since 2.088.0

    union U
    {
        int a;
        long b = 4;
    }
    

    This is problematic because unions are default initialized to whatever the initializer for the first field is, any other initializers present are ignored.

    The corrective action is to declare the union field with the default initialization as the first field.

Runtime changes

  1. TypeInfo names for aggregates are fully qualified and hence unique now

    Previously, template arguments weren't fully qualified; they now are, implying longer names in that case.

    TypeInfo_Struct instances now store the (potentially significantly shorter) mangled name only and demangle it lazily on the first name or toString() call (with a per-thread cache). So if you only need a unique string per struct TypeInfo, prefer mangledName over computed name (non-@nogc and non-pure).

    Related breaking change: TypeInfo.toString() isn't pure anymore to account for the TypeInfo_Struct demangled name cache. TypeInfo_Class.toString() and others are still pure.

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

  3. 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));
    assert(isValidCharacter('ä'));
    

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 13009: [REG2.064] inout overload conflicts with non-inout when used via alias this
  2. Bugzilla 21238: -deps considers only the first instantiation site of a template for dependencies
  3. Bugzilla 21850: [REG2.093] Template inference of pure not working
  4. Bugzilla 22035: [REG 2.097][ICE] Segmentation fault parsing invalid case statement
  5. Bugzilla 22054: Referencing a fwd-declared field results in many error messages
  6. 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'
  7. Bugzilla 22086: importC: RangeError@src/dmd/dscope.d(469): Range violation
  8. Bugzilla 22118: Const union causes false multiple-initialization error in constructor
  9. Bugzilla 22121: [REG 2.097][ICE] Segmentation fault in in dmd.dsymbol.ScopeDsymbol.addAccessiblePackage
  10. Bugzilla 22122: [REG 2.097][ICE] Segmentation fault in in dmd.access.hasPackageAccess
  11. Bugzilla 22196: importC: Error: found const when expecting )in __attribute__
  12. Bugzilla 22205: catch(Exception) not longer working in debug blocks
  13. Bugzilla 22214: Regression 2.097.0: __traits(compiles) doesn't notice invalid getMember that yields type
  14. Bugzilla 22224: [REG 2.097.0] compiler segfaults with -profile
  15. Bugzilla 22226: [REG 2.095.1] __ctfe + function call in conditional expression used to initialize struct member in constructor causes ICE
  16. Bugzilla 22228: [CTFE] taking address of immutable in frame function causes ICE on Unix platforms
  17. Bugzilla 22292: REG[2.084.1] Recursive class literal segfaults compiler

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 [email protected](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 22246: importC: C11 does not allow _Alignof (expression)
  69. Bugzilla 22250: ImportC: Array subscripts do not comply with C standard.
  70. Bugzilla 22252: ImportC: Array, Function parameter types should be converted to pointers
  71. Bugzilla 22253: ImportC expressions inadvertently supporting D properties
  72. Bugzilla 22262: importC: Error: incompatible types for '(buf) is (0)': 'ubyte*' and 'int'
  73. Bugzilla 22263: ImportC: function and variable re-declarations should be allowed
  74. Bugzilla 22264: importC: Error: '=', ';' or ',' expected using K&R function syntax
  75. Bugzilla 22265: importC: Error: cannot modify 'const' expression
  76. Bugzilla 22274: importC: [ICE]: 4 identifiers does not match 3 declarations using K&R syntax
  77. Bugzilla 22275: importC: Error: incompatible types for (dest) !is (buf): char* and char[1]
  78. Bugzilla 22286: importC: (identifier)(other_identifier) incorrectly parsed as a cast-expression
  79. Bugzilla 22294: importC: enums aren’t placed in surrounding namespace.
  80. Bugzilla 22303: ImportC: pragma directives should be ignored
  81. Bugzilla 22304: importC: parsing gnu-style attributes fails if return type is pointer
  82. Bugzilla 22312: importC: redundant typedefs are rejected
  83. Bugzilla 22313: ImportC: account for ( ) when doing lookahead on assignment-expressions
  84. Bugzilla 22314: ImportC: fails to parse gnu attributes on enum members
  85. Bugzilla 22321: ImportC: non-static arrays can’t be initialized by an initializer list.
  86. Bugzilla 22322: ImportC: struct with floating point members causes problems with generated toHash() function
  87. Bugzilla 22326: ImportC: struct with flexible array member is incorrectly handled
  88. Bugzilla 22329: DMD and LDC2 Segumentation Faults due to alias this on private field + special names
  89. Bugzilla 22333: ImportC: fails to parse enumerators with = and gnu attributes
  90. Bugzilla 22373: Glue layer rejects cast from noreturn to other type

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

dlang.org 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

dlang.org 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