Change Log: 2.109.0
Download D 2.109.0
released Jun 01, 2024
Compiler changes
- [next edition] Aliasing a member of a type instance is now an error
- Add Bitfield Introspection Capability
- Added __ctfeWrite to write messages from CTFE
- Deprecation warnings are now also limited by -verrors
- dtoh generates signatures for extern(Windows) and extern(System) functions.
- foreach on a dynamic array can have an index type smaller than size_t
- foreach_reverse on a delegate is now an error
- Expansion of identifier tables to allow new characters to match C23 have been added along with CLI configurability
- ImportC has improved Unicode support
- Missing symbol errors are made less cryptic
- Windows OMF support has been removed
Runtime changes
Library changes
List of all bug fixes and enhancements in D 2.109.0.
Compiler changes
- [next edition] Aliasing a member of a type instance is now an error
Such an alias actually aliases a member of the instance's type, not the instance member itself. That could be confusing, and is now an error. Instead, alias a member of the type:
struct Foo { int v; void test(Foo that) const { alias a = this.v; // OK alias b = that.v; // Error, use `typeof(that).v` instead assert(&a is &b); // passes assert(&b !is &that.v); } } struct Bar { Foo f; alias v = f.v; // Error, use `typeof(f).v` }
- Add Bitfield Introspection Capability
Adds:
- property .bitoffsetof to get the starting bit number of a bitfield
- property .bitwidth to get the number of bits in a bitfield
- __traits(isBitfield, symbol) returns true if a field symbol is a bitfield
- Added __ctfeWrite to write messages from CTFE
The special function __ctfeWrite can now be used to write messages during CTFE, similar to pragma(msg, ...). It is Implementation Defined how the message is presented to the user; the recommended way is by printing the message to stderr, standard error stream. The function is available in object.d and accepts any value implicitly convertible to const(char)[].
For example:
int greeting() { __ctfeWrite("Hello from CTFE. Today is "); __ctfeWrite(__DATE__); __ctfeWrite("\n"); return 0; } enum forceCTFE = greeting();
Compiling this program will generate the following output:
Hello from CTFE. Today is <current date>
- Deprecation warnings are now also limited by -verrors
By default, the compiler stops after 20 error messages, unless a different amount is specified by passing e.g. -verrors=50 or -verrors=0 for no limit. This error limit now also applies to deprecation messages, so the command line isn't flooded with hundreds of them when compiling a big project that hasn't fixed all deprecations yet.
deprecated void f() { } void main() { f(); f(); f(); f(); }
> dmd -verrors=3 app.d app.d(7): Deprecation: function app.f is deprecated app.d(8): Deprecation: function app.f is deprecated app.d(9): Deprecation: function app.f is deprecated 1 deprecation warning omitted, use -verrors=0 to show all
- dtoh generates signatures for extern(Windows) and extern(System) functions.
When using the -HC switch, in addition to extern(C) and extern(C++) functions, extern(Windows) and extern(System) functions are output in the .h file as well.
Example D module:
extern(Windows) int hello() { return 0; } extern(System) int myFriend() { return 0; }
Output with -HC switch:
// (full header omitted) #ifndef _WIN32 #define EXTERN_SYSTEM_AFTER __stdcall #define EXTERN_SYSTEM_BEFORE #else #define EXTERN_SYSTEM_AFTER #define EXTERN_SYSTEM_BEFORE extern "C" #endif int32_t __stdcall hello(); EXTERN_SYSTEM_BEFORE int32_t EXTERN_SYSTEM_AFTER myFriend(x);
- foreach on a dynamic array can have an index type smaller than size_t
The array length is known at compile-time for the following cases:
- The array is a literal
- The array is a slice expression whose upper bound is known at compile-time
For an array a, the index type can be any integer type I where a.length <= I.max.
Other cases are not implemented yet.
- foreach_reverse on a delegate is now an error
The compiler did not try to implement reverse traversal of the results returned by the delegate when foreach_reverse was used. That could result in code that was confusing to read, so it was deprecated (for many years). Using foreach_reverse with a delegate is now an error.
- Expansion of identifier tables to allow new characters to match C23 have been added along with CLI configurability
You can currently choose between c99, c11, UAX31 (C23's) and all (the least restrictive set) for both D and ImportC.
This can be done with -identifiers=<table> and for ImportC -identifiers-importc=<table>.
The default table for D is currently set to all, while ImportC is set to c11. Previously both D and ImportC used the c99 tables.
D's table will be swapped over at a later date to UAX31, this should be done in 2.117. If you find yourself at this time using c99 specific characters and not willing to change them, you may switch back to all. Although it should be unlikely that you will need to.
- ImportC has improved Unicode support
Universal Character Names are now supported, allowing you to use the \uXXXX and \UXXXXXXXX syntax where X is a hex digit as part of an identifier.
DigitalMars sppn does not support anything newer than C99. It is known to be limited and using any Unicode character not in those ranges will result in an error.
- Missing symbol errors are made less cryptic
It is not uncommon to forget to link a library, list a .d file on the command line, or include a main function. Example:
module app; unittest { import assertions; assertEquals('D', 'D'); }
module assertions; void assertEquals(char a, char b) { assert(a == b); }
When compiling this as follows:
> dmd -unittest app.d
The compiler would not see any error, but at link time there are missing symbols. Formerly, this would result in a cryptic linker error with mangled symbol names:
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../lib/Scrt1.o: in function `_start': (.text+0x1b): undefined reference to `main' /usr/bin/ld: app.o: in function `_D3app16__unittest_L5_C1FZv': app.d:(.text._D3app16__unittest_L5_C1FZv[_D3app16__unittest_L5_C1FZv]+0xc): undefined reference to `_D10assertions12assertEqualsFaaZv' collect2: error: ld returned 1 exit status
Experienced users might know how to demangle the symbol to make it more readable:
> echo _D10assertions12assertEqualsFaaZv | ddemangle void assertions.assertEquals(char, char)
But this is inconvenient to do manually every time. Now, when the compiler invokes the linker program, it will read its output, scan for undefined symbol errors, and demangle the names:
Error: undefined reference to main Error: undefined reference to void assertions.assertEquals(char, char) referenced from void app.__unittest_L5_C1() perhaps define a void main() {} function or use the -main switch perhaps .d files need to be added on the command line, or use -i to compile imports Error: linker exited with status 1
Which makes it easier to fix the command:
> dmd -unittest -main -i app.d
Currently supported linkers are ld, bfd, gold, mold, and Microsoft LINK. Please file an issue if your linker's errors aren't detected.
- Windows OMF support has been removed
After two years of making PE-COFF support the default on Windows, OMF support has now been removed.
This includes the switch (-m32omf).
Runtime changes
- Add module core.sys.linux.sys.mount.
The new module core.sys.linux.sys.mount provides definitions corresponding to those in the header <sys/mount.h> on Linux.
- Remove all collectNoStack functions and API from druntime.
The function collectNoStack in the D garbage collector performed a collection, without using any roots from thread stacks or thread-local-storage. The danger of running this mechanism is that any blocks of memory which only have a reference from a thread might be collected, while the thread is still running and possibly using the memory.
The only time this function was called was at GC termination. At GC termination, the GC is about to be destroyed, and so we want to run as many destructors as possible. However, if some thread is using GC-allocated memory, cleaning up that memory isn't going to help matters. Either it will crash after the GC cleans the memory, or it will crash after the GC is destroyed.
The original purpose of this function (from D1) was to ensure simple uses of the GC were cleaned up in small test programs, as this mechanism was only used on single-threaded programs (and of course, at program exit). Also note at the time, D1 was 32-bit, and false pointers where much more common. Avoiding scanning stacks would aid in avoiding seemingly random behavior in cleanup. However, as shown below, there are more deterministic ways to ensure data is always cleaned up.
Today, the dangers are much greater that such a function is even callable -- any call to such a function would immediately start use-after-free memory corruption in any thread that is still running. Therefore, we are removing the functionality entirely, and simply doing a standard GC cleanup (scanning stacks and all). One less footgun is the benefit for having less guaranteed GC clean up at program exit.
In addition, the GC today is a bit smarter about where the valid stack is, so there is even less of a chance of leaving blocks unfinalized.
As always, the GC is not guaranteed to clean up any block at the end of runtime. Any change in behavior with code that had blocks clean up before, but no longer are cleaned up is still within specification. And if you want the behavior that absolutely cleans all blocks, you can use the --DRT-gcopt=cleanup:finalize druntime configuration option, which will clean up all blocks without even scanning.
- Mark Thread.sleep as @trusted
The static method core.thread.Thread.sleep is now marked as @trusted and can be called directly from @safe code.
Library changes
- Add std.process.Config.preExecDelegate
std.process.Config.preExecDelegate is just like std.process.Config.preExecFunction, but can capture an environment, for example:
import core.sys.linux.sys.prctl : PR_SET_PDEATHSIG, prctl; import std.process : Config, execute; void runProgram(int pdeathsig) { execute( ["program"], config: Config( preExecDelegate: () @trusted => prctl(PR_SET_PDEATHSIG, pdeathsig, 0, 0, 0) != -1, ), ); }
preExecFunction is retained for backwards compatibility. If both preExecFunction and preExecDelegate are given, both are called.
List of all bug fixes and enhancements in D 2.109.0:
DMD Compiler regression fixes
- Bugzilla 24560: dmd crash on imported function with default parameter containing new
DMD Compiler bug fixes
- Bugzilla 14128: AliasDeclaration allows expressions, causing false code for ThisExp
- Bugzilla 20148: void initializated bool can be both true and false
- Bugzilla 21854: @live breaks foreach over integers
- Bugzilla 21923: @live does not take destructor code into account.
- Bugzilla 22977: [dip1000] can escape scope pointer returned by nested function
- Bugzilla 23530: casting immutable away allowed in safe
- Bugzilla 24434: Casting away const with cast() should not produce an lvalue
- Bugzilla 24477: Union access of bool shouldn't be allowed in @safe
- Bugzilla 24485: Invalid implicit ref return reinterpret cast for structs with copy constructor
- Bugzilla 24493: FreeBSD_14 version identifier missing
- Bugzilla 24504: ImportC: Enum declarations with a mixture of int and uint literal values cause errors, when targeting Windows, when debug info generation is enabled.
- Bugzilla 24520: [REG] type(value) got a synonym (type)(value)
- Bugzilla 24525: auto ref lambda exp not parsed if used as left-most expression in an expression statement
DMD Compiler enhancements
- Bugzilla 5573: Compiler (not linker) should generate an error for missing main()
- Bugzilla 21718: Preview switches have insufficient descriptions
- Bugzilla 24111: [ImportC] fatal error C1034: stdio.h: no include path set
- Bugzilla 24450: apply VRP to foreach indices when array is of known length
- Bugzilla 24452: Can't disable coverage at runtime
Phobos bug fixes
- Bugzilla 15708: std.range.choose assumes hasElaborateCopyConstructor means "has __postblit"
- Bugzilla 24478: std.csv array out of bounds when row size exceeds header
- Bugzilla 24549: std.process.environment.get(null) segfaults
Druntime bug fixes
- Bugzilla 24517: druntime tests fail on FreeBSD 14
- Bugzilla 24546: importC musl setjmp.h failure
dlang.org bug fixes
- Bugzilla 24472: __traits(fullyQualifedName) is undocumented in spec
dlang.org enhancements
- Bugzilla 24488: contributor guide hard to find from home page
Contributors to this release (39)
A huge thanks goes to all the awesome people who made this release possible.
- 0-v-0
- Adam Wilson
- Andrei Horodniceanu
- Ate Eskola
- Bastiaan Veelo
- Ben Jones
- chloekek
- Denis Feklushkin
- Dennis
- Dennis Korpel
- dokutoku
- Don Allen
- drug007
- Emmanuel Nyarko
- Harry Gillanders
- Horodniceanu Andrei
- Iain Buclaw
- IchorDev
- Inkrementator
- Jeremy Baxter
- Johan Engelen
- John Dougan
- Jonathan M Davis
- liushuyu
- Martin Kinkelin
- Matheus C. França
- Mathis Beer
- Nick Treleaven
- Paul Backus
- Petar Kirov
- Razvan Nitu
- Richard (Rikki) Andrew Cattermole
- shoo
- Steven Schveighoffer
- Sönke Ludwig
- Vladimir Panteleev
- Walter Bright
- WANG Rui
- zopsicle