Change Log: 2.098.0
Download D 2.098.0
released Oct 10, 2021
Compiler changes
- Add Alias Assignment
- Accessing C Declarations From D Via ImportC Compiler
- Using the syntax (args) => {} now triggers a deprecation message
- Improvements for the C++ header generation
- -preview=dtorfields is now enabled by default
- Add .min, .max, etc. properties for vector types.
- Using a mutable variable as a switch case now triggers an error
- Out of bounds array access now gives a better error message
- Class allocators have been removed from the language
- Initialization of immutable global data from static this now triggers an error
- Add -target=<triple> for operating system, c, and c++ runtime cross compilation
- Default initialization of union field that isn't the first member now triggers an error
Runtime changes
Library changes
Dub changes
List of all bug fixes and enhancements in D 2.098.0.
Compiler changes
- 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.
- 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
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
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:
- Compile C code directly, but only C code that has already been run through
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.
- A C compiler front end, stripped of its integrated preprocessor, is a simple
- The D part of dmd will have no idea it originated as C code. It would be
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.
- Pretty-printing code is done in D syntax, not C. Also,
- No warnings are emitted. ImportC doesn't care about coding style,
- If the ImportC code corrupts memory, overflows buffers, etc.,
- Symbolic debugging support is there.
Variance From ISO C11
- Doesn't have a C Preprocessor.
- Tag symbols are part of the global symbol table, not the special tag
- 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
- { 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
- Semantics applied after C parsing are D semantics, not C semantics,
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
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.
- 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.
- 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 */ }.
- 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.
- -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.
- 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);
- 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.
- 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.
- 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.
- 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.
- 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_64 64 bit x64 64 bit x86 32 bit x32 64bit with 32 bit pointers subarch features equivalent -mcpu flag +sse2 baseline +avx avx +avx2 avx2 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 freestanding No operating system darwin MacOS dragonfly DragonflyBSD freebsd FreeBSD openbsd OpenBSD linux Linux solaris Solaris windows Windows <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.
| glibc | GCC C runtime | linux | | newlib | Newlib Libc | | | uclibc | uclibc | |<cenv> C runtime environment Default for OS musl musl-libc msvc MSVC runtime Windows bionic Andriod libc digital_mars Digital Mars C runtime for Windows <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 environment Default for OS clang LLVM C++ runtime MacOS, FreeBSD, OpenBSD, DragonflyBSD gcc GCC C++ runtime linux msvc MSVC runtime Windows digital_mars Digital Mars C++ runtime for Windows sun Sun C++ runtime Solaris - 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
- 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.
- 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.
- 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
- 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
- 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
- Bugzilla 13009: [REG2.064] inout overload conflicts with non-inout when used via alias this
- Bugzilla 21238: -deps considers only the first instantiation site of a template for dependencies
- Bugzilla 21850: [REG2.093] Template inference of pure not working
- Bugzilla 22035: [REG 2.097][ICE] Segmentation fault parsing invalid case statement
- Bugzilla 22054: Referencing a fwd-declared field results in many error messages
- 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'
- Bugzilla 22086: importC: RangeError@src/dmd/dscope.d(469): Range violation
- Bugzilla 22118: Const union causes false multiple-initialization error in constructor
- Bugzilla 22121: [REG 2.097][ICE] Segmentation fault in in dmd.dsymbol.ScopeDsymbol.addAccessiblePackage
- Bugzilla 22122: [REG 2.097][ICE] Segmentation fault in in dmd.access.hasPackageAccess
- Bugzilla 22196: importC: Error: found const when expecting )in __attribute__
- Bugzilla 22205: catch(Exception) not longer working in debug blocks
- Bugzilla 22214: Regression 2.097.0: __traits(compiles) doesn't notice invalid getMember that yields type
- Bugzilla 22224: [REG 2.097.0] compiler segfaults with -profile
- Bugzilla 22226: [REG 2.095.1] __ctfe + function call in conditional expression used to initialize struct member in constructor causes ICE
- Bugzilla 22228: [CTFE] taking address of immutable in frame function causes ICE on Unix platforms
- Bugzilla 22292: REG[2.084.1] Recursive class literal segfaults compiler
DMD Compiler bug fixes
- Bugzilla 13165: Using -profile does extra control flow analysis, leading to spurious statement is not reachable warning
- Bugzilla 14064: Error message about @ attributes incomplete.
- Bugzilla 15631: gdb: Parent's scope not considered for symbol lookup
- Bugzilla 16274: The curses of debugging: short argument passed in 16-bit register, against ABI
- Bugzilla 17041: foreach-ref can't use to static array's AliasSeq
- Bugzilla 20150: -dip1000 defeated by pure
- Bugzilla 20245: DIP1000: Should infer scope when taking address of ref
- Bugzilla 21209: scope attribute inference with does not work well with foreach
- Bugzilla 21868: DIP1000 doesn't catch pointer to struct temporary
- Bugzilla 21905: case of IFTI failure when combining ref, and alias this on a static instance
- Bugzilla 21928: Wrong location for "array literal in @nogc function main may cause GC allocation" error
- Bugzilla 21931: importC: 'alias time_t = time_t;' cannot alias itself, use a qualified name to create an overload set
- Bugzilla 21932: importC: enum 'ENUM' conflicts with enum 'ENUM'
- Bugzilla 21933: importC: struct parameters: AssertError@src/dmd/typesem.d(1890): Assertion failure
- Bugzilla 21934: importC: Support asm labels to specify the assembler name to use for a C symbol
- Bugzilla 21937: importC: Support parsing __attribute specifiers
- Bugzilla 21939: Duplicate error messages for wrong aggregate in 'static foreach'
- Bugzilla 21942: importC: Support parsing __inline__ keyword
- Bugzilla 21944: importC: Support parsing # line marker directive extensions
- Bugzilla 21945: importC AssertError@src/dmd/dsymbolsem.d(4787): Assertion failure
- Bugzilla 21946: importC: Support parsing __extension__ keyword
- Bugzilla 21948: importC: Support declaring local variables of typedef types
- Bugzilla 21949: noreturn doesn't follow covariance rules
- Bugzilla 21962: importC: Empty enums are accepted as valid code
- Bugzilla 21963: importC: Support declaring union types
- Bugzilla 21965: importC: Anonymous top-level struct or union triggers [email protected](4787)
- Bugzilla 21967: importC: Error function without 'this' cannot be 'const'
- Bugzilla 21968: importC: struct fields: AssertError@src/dmd/typesem.d(1890): Assertion failure
- Bugzilla 21970: importC: Error: variable extern symbols cannot have initializers
- Bugzilla 21973: importC: AssertError@src/dmd/dsymbolsem.d(4307): Assertion failure
- Bugzilla 21976: importC: does not distinguish between cast-expression and unary-expression correctly
- Bugzilla 21977: importC: Global declarations are thread-local by default
- Bugzilla 21982: importC: Error: variable no definition of struct
- Bugzilla 21985: "goto" errors with unexistent label report wrong/misleading line
- Bugzilla 21992: importC: Error: variable is used as a type
- Bugzilla 21994: (char*)"string" fails to compile
- Bugzilla 22005: ICE: Segmentation fault with static foreach and -betterC
- Bugzilla 22006: static foreach and foreach over tuple doesn't work on 16-bit
- Bugzilla 22007: static foreach: cannot implicitly convert expression Tuple4(0LU, 1) of type Tuple4 to int
- Bugzilla 22019: case 1,: allowed by grammar but not DMD
- Bugzilla 22028: importC: Parser accepts initializers for struct members
- Bugzilla 22029: importC: Parser accepts storage-class specifiers for fields
- Bugzilla 22030: importC: Wrong error with bad declarator
- Bugzilla 22032: importC: infinite loop: illegal combination of type specifiers
- Bugzilla 22053: catch { not rejected while in a template
- Bugzilla 22060: importC: Multiple forward declarations result in error struct conflicts with struct
- Bugzilla 22063: importC: Error: undefined identifier 'var' with pointer-to-typedef type
- Bugzilla 22066: importC: Error: expression expected, not ';' using (postfix-expression)++
- Bugzilla 22067: importC: cast-expression accepted as lvalue in assignment-expression
- Bugzilla 22068: importC: cast-expression accepted as lvalue in unary-expression
- Bugzilla 22069: importC: Error: found '&' instead of statement
- Bugzilla 22070: importC: Error: string literal is not an lvalue
- Bugzilla 22071: importC: Error: struct literal is not an lvalue
- Bugzilla 22073: importC: Error: found '.' when expecting ';' following compound literal
- Bugzilla 22079: importC: Error: '=', ';' or ',' expected taking sizeof compound literal
- Bugzilla 22080: ImportC: Error: cannot implicitly convert expression of type 'extern(C) function' to 'function'
- Bugzilla 22088: ImportC: C11 6.3 semantics on implicit conversions is not implemented
- Bugzilla 22102: importC: Error: function is used as a type
- Bugzilla 22103: importC: Parser accepts wrong syntax for array declarators
- Bugzilla 22106: importC: Error: variable 'var' no definition of struct 'type'
- Bugzilla 22126: -checkaction=context should not print overlapped struct members
- Bugzilla 22149: TypeInfo_Struct names aren't unique, leading to botched equality semantics
- Bugzilla 22150: TypeInfo_Class names aren't unique, leading to botched equality semantics
- Bugzilla 22160: importC: Error: redeclaring module test as struct test
- Bugzilla 22180: .alignof not working for globals
- Bugzilla 22182: importC: Error: expression expected, not ) when casting pointer with redundant parens.
- Bugzilla 22209: NRVO variable detection ignoring alias this conversion => segfaults
- Bugzilla 22246: importC: C11 does not allow _Alignof (expression)
- Bugzilla 22250: ImportC: Array subscripts do not comply with C standard.
- Bugzilla 22252: ImportC: Array, Function parameter types should be converted to pointers
- Bugzilla 22253: ImportC expressions inadvertently supporting D properties
- Bugzilla 22262: importC: Error: incompatible types for '(buf) is (0)': 'ubyte*' and 'int'
- Bugzilla 22263: ImportC: function and variable re-declarations should be allowed
- Bugzilla 22264: importC: Error: '=', ';' or ',' expected using K&R function syntax
- Bugzilla 22265: importC: Error: cannot modify 'const' expression
- Bugzilla 22274: importC: [ICE]: 4 identifiers does not match 3 declarations using K&R syntax
- Bugzilla 22275: importC: Error: incompatible types for (dest) !is (buf): char* and char[1]
- Bugzilla 22286: importC: (identifier)(other_identifier) incorrectly parsed as a cast-expression
- Bugzilla 22294: importC: enums aren’t placed in surrounding namespace.
- Bugzilla 22303: ImportC: pragma directives should be ignored
- Bugzilla 22304: importC: parsing gnu-style attributes fails if return type is pointer
- Bugzilla 22312: importC: redundant typedefs are rejected
- Bugzilla 22313: ImportC: account for ( ) when doing lookahead on assignment-expressions
- Bugzilla 22314: ImportC: fails to parse gnu attributes on enum members
- Bugzilla 22321: ImportC: non-static arrays can’t be initialized by an initializer list.
- Bugzilla 22322: ImportC: struct with floating point members causes problems with generated toHash() function
- Bugzilla 22326: ImportC: struct with flexible array member is incorrectly handled
- Bugzilla 22329: DMD and LDC2 Segumentation Faults due to alias this on private field + special names
- Bugzilla 22333: ImportC: fails to parse enumerators with = and gnu attributes
- Bugzilla 22373: Glue layer rejects cast from noreturn to other type
DMD Compiler enhancements
- Bugzilla 15889: Array bounds check should report index and length
- Bugzilla 16001: Lambda syntax: forbid use with FunctionLiteralBody: (x) => {assert(x);}
- Bugzilla 16689: Errors in instantiated mixin templates should show instantiation point
- Bugzilla 17400: put a new line before "candidates are:" in error messages
- Bugzilla 18907: Support cross-compiling
- Bugzilla 21885: Bad diagnostic: struct is not copyable because it is annotated @disable
- Bugzilla 21997: CTFE should allow function pointer casts with different attributes
- Bugzilla 22038: final switch error message should report all missing enum members
- Bugzilla 22115: Optimize if (s.a == 3 ? s : null) to if (s.a == 3)
- Bugzilla 22138: foreach cannot declare the loop variables as scope
- Bugzilla 22227: if (scope f = x()) and while (scope f = x()) do not parse
Phobos regression fixes
- Bugzilla 21920: [REG master] Error: auto can only be used as part of auto ref for template function parameters
Phobos bug fixes
- Bugzilla 19727: std.algorithm.endsWith fails to compile while startsWith succeeds
- Bugzilla 20393: formattedRead accepts input, that should be rejected
- Bugzilla 20937: std.range.array of a lengthless range with indirection is not @safe
- Bugzilla 21916: Error message is obfuscated when using wrong format specifier at compile-time
- Bugzilla 22001: Equality of std.conv.toChars() results for radix 10 depends on uninitialized bytes
- Bugzilla 22077: std.sumtype support for copy constructors is incomplete
- Bugzilla 22101: Nullable.get(fallback) cannot be used with non-@safe/pure/nothrow types
- Bugzilla 22110: isCallable fails for template opCall without any templated argument
- Bugzilla 22140: FunctionTypeOf fails for template opCall without any templated argument
- Bugzilla 22146: std.algorithm.searching.findAdjacent() can fall off end of function
- Bugzilla 22222: Custom unittest runner on phobos fails due to segfault on fork() exiting
Phobos enhancements
- Bugzilla 16210: std.utf.byUTF can be made into a bidirectional range
- Bugzilla 16218: Windows std.file.readImpl should be marked @system
- Bugzilla 18632: enable use of fromStringz with char[n]
- Bugzilla 20665: std.concurrency.spawn should document not working with delegates
- Bugzilla 21926: Allow leading zeros in std.conv.octal
- Bugzilla 22100: Support chained assignment of Nullable
- Bugzilla 22225: SumType: Some assignments should be able to execute in safe code
Druntime bug fixes
- Bugzilla 9799: Missing aliases and enums in druntime imports
- Bugzilla 14439: aa's keys, values not usable in @safe context
- Bugzilla 21550: core.memory.__delete does not actually work
- Bugzilla 21983: dup leaves a partially constructed array if postblit/copy ctor throws
- Bugzilla 21996: -checkaction=context triggers InvalidMemoryOperationError in finalizer
- Bugzilla 22024: hashOf does not work on enum types whose base type is a SIMD vector
- Bugzilla 22026: checkaction=context: Exception thrown by toString hides assertion failures
- Bugzilla 22076: hashOf(S) can segfault if S.toHash is forwarded via 'alias this' to a receiver which may be null
- Bugzilla 22081: DWARF v5 support is utterly broken - 'illegal instruction' when throwing exceptions
- Bugzilla 22085: checkaction=context doesn't support extern(C++) classes
- Bugzilla 22107: [scope][dip1000] Can't .dup an array of structs with impure copy constructor
- Bugzilla 22143: Throwable ctor doesn't increment chained exception's ref count
- Bugzilla 22218: Dynamic casts across binary boundaries can easily fail
Druntime enhancements
- Bugzilla 22169: Mark as pure core.sys.posix.string: memccpy, stpcpy, stpncpy, strnlen
dlang.org bug fixes
- Bugzilla 3345: Static and nonstatic methods with the same name should be allowed
- Bugzilla 20557: Spec does not allow StringPostfix after DelimitedString or TokenString while implementation does
- Bugzilla 21125: Typo in std.range.refRange documentation for opIndex
- Bugzilla 21906: obscure sentence in the introduction to phases of compilation
- Bugzilla 21935: Broken Link in Lazy Evaluation Article
- Bugzilla 22229: Struct initialization via constructor missing from language spec
dlang.org enhancements
- Bugzilla 21495: File.readf documentation does not state what what is returned.
- Bugzilla 21600: Regex.namedCaptures is undocumented
Installer bug fixes
- 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.
- Adam D. Ruppe
- aG0aep6G
- Airbus5717
- Andrei Alexandrescu
- Andrei David
- Andrej Petrović
- Ate Eskola
- Atila Neves
- avaj
- Basile Burg
- Ben Jones
- berni44
- Boris Carvajal
- Brandon Mitchell
- Brian Callahan
- Cameron Ross
- Carsten Schlote
- Craig Barnes
- dandrei279
- Dennis
- dkorpel
- DoctorNoobingstoneIPresume
- drug007
- Etienne Brateau
- Florian
- Hiroki Noda
- Iain Buclaw
- Johan Engelen
- John Colvin
- João Lourenço
- linkrope
- lucica28
- Luís Ferreira
- Martin Kinkelin
- Martin Nowak
- Mathias Lang
- Mathis Beer
- Max Haughton
- Mike Parker
- MoonlightSentinel
- Nathan Sashihara
- Nicholas Wilson
- nordlow
- Paul Backus
- Per Nordlöw
- Rainer Schuetze
- Ramanuj
- Razvan Nitu
- Richard Manthorpe
- RUSshy
- Sebastian Wilzbach
- Simen Kjærås
- Sinisa Susnjar
- Stefan Koch
- Teodor Dutu
- Tomoya Tanjo
- TungstenHeart
- vladchicos
- Vladimir Panteleev
- Walter Bright
- Walter Waldron
- Witold Baryluk