Change Log: 2.093.0
Download D nightlies
To be released
This changelog has been automatically generated from all commits in master since the last release.
- The full-text messages are assembled from the changelog/ directories of the respective repositories: dmd, druntime, phobos, tools, dlang.org, installer, and dub.
- See the DLang-Bot documentation for details on referencing Bugzilla. The DAutoTest PR preview doesn't include the Bugzilla changelog.
- The pending changelog can be generated locally by setting up dlang.org and running the pending_changelog target:
make -f posix.mak pending_changelog
Compiler changes
- CLI switches -revert=import and -transition=checkimports have been removed
- Added support for mangling C++'s GNU ABI tags
- Module constructors and destructors which are not extern(D) are deprecated
- DIP25 violations will now issue deprecations by default
- Prototype Ownership/Borrowing System for Pointers
- Added -preview=in to make the in storage class mean scope const.
- Validate printf and scanf (variants too) arguments against format specifiers
- Environment variable SOURCE_DATE_EPOCH is now supported
Runtime changes
Library changes
Dub changes
List of all upcoming bug fixes and enhancements in D 2.093.0.
Compiler changes
- CLI switches -revert=import and -transition=checkimports have been removed
Those switched were already not doing anything and had been deprecated for a while. The compiler will no longer recognized them.
- Added support for mangling C++'s GNU ABI tags
GNU ABI tags are a feature that was added with C++11 in GCC 5.1. In order for D to fully support the standard C++ library, DMD now recognize the special UDA gnuAbiTag, declared in core.attribute and publicly aliased in object (so one need not import anything to use it). The ABI tags are a low level feature that most user will not need to interact with, but can be used to bind to C++ libraries that need it. In particular, it is required to bind std::string when targeting C++11 and higher (DMD switch -extern-std={c++11,c++14,c++17}).
It can be used in the following way:
extern(C++): @gnuAbiTag("tagOnStruct") struct MyStruct {} @gnuAbiTag("Multiple", "Tags", "On", "Function") MyStruct func();
Only one gnuAbiTag can be present on a symbol at a time. The order of the array entries does not matter (they are sorted on output). The UDA will only have an effect if -extern-std=c++11 or higher is passed to the compiler. The default (-extern-std=c++98) will ignore the UDA. This UDA can only be applied to extern(C++) symbols and cannot be applied to namespaces.
- Module constructors and destructors which are not extern(D) are deprecated
Module constructors and destructors (shared or not) could be marked with a different linkage than extern(D), which would affect their mangling. Since such a mangling is simple and predictable, there was a very small chance of conflict if two same kind of constructor/destructors were declared in similar condition, for example if the third module constructor in module a was on line 479 and the third module constructor in module b was also on line 479, they would have the same mangling.
While it's unlikely that such a bug is triggered in practice, affected symbols will now trigger a deprecation message.
- DIP25 violations will now issue deprecations by default
DIP25 has been available since v2.067.0, first as its own switch, and more recently under the -preview=dip25 switch. The feature is now fully functional and has been built on, for example by DIP1000.
Starting from this release, code that would trigger errors when -preview=dip25 is passed to the compiler will also trigger a deprecation message without -preview=dip25. The behavior of the switch is unchanged (errors will still be issued).
DIP25 aims to make it impossible for @safe code to refer to destructed object. In practice, functions and methods returning a ref to their parameter might be required to qualify the method or the parameter as return, as hinted by the compiler.
struct Foo { int x; // returning `this.x` escapes a reference to parameter `this`, perhaps annotate with `return` ref int method() /* return */ { return this.x; } } // returning `v` escapes a reference to parameter `v`, perhaps annotate with `return` ref int identity(/* return */ ref int v) { return v; }
In both cases, uncommenting the return annotation will appease the compiler. The complete description of DIP25 can be found here.
- Prototype Ownership/Borrowing System for Pointers
An Ownership/Borrowing (aka OB) system for pointers can guarantee that dereferenced pointers are pointing to a valid memory object.
Scope of Prototype OB System
This is a prototype OB system adapted to D. It is initially for pointers only, not dynamic arrays, class references, refs, or pointer fields of aggregates. Adding support for such adds complexity, but does not change the nature of it, hence it is deferred to later. RAII objects can safely manage their own memory, so are not covered by OB. Whether a pointer is allocates memory using the GC or some other storage allocator is immaterial to OB, they are not distinguished and are handled identically.
The system is only active in functions annotated with the @live attribute. It is applied after semantic processing is done as purely a check for violations of the OB rules. No new syntax is added. No change is made to the code generated. If @live functions call non-@live functions, those called functions are expected to present an @live compatible interface, although it is not checked. if non-@live functions call @live functions, arguments passed are expected to follow @live conventions.
The OB system will detect as errors:
- dereferencing pointers that are in an invalid state
- more than one active pointer to a mutable memory object
It will not detect attempts to dereference null pointers or possibly null pointers. This is unworkable because there is no current method of annotating a type as a non-null pointer.
Core OB Principle
The OB design follows from the following principle:
For each memory object, there can exist either exactly one mutating pointer to it, or multiple non-mutating (read-only) pointers.
Design
The single mutating pointer is called the "owner" of the memory object. It transitively owns the memory object and all memory objects accessible from it (i.e. the memory object graph). Since it is the sole pointer to that memory object, it can safely manage the memory (change its shape, allocate, free and resize) without pulling the rug out from under any other pointers (mutating or not) that may point to it.
If there are multiple read-only pointers to the memory object graph, they can safely read from it without being concerned about the memory object graph being changed underfoot.
The rest of the design is concerned with how pointers become owners, read only pointers, and invalid pointers, and how the Core OB Principle is maintained at all times.
Tracked Pointers
The only pointers that are tracked are those declared in the @live function as this, function parameters or local variables. Variables from other functions are not tracked, even @live ones, as the analysis of interactions with other functions depends entirely on that function signature, not its internals. Parameters that are const are not tracked.
Pointer States
Each pointer is in one of the following states:
- Undefined
- The pointer is in an invalid state. Dereferencing such a pointer is an error.
- Owner
- The owner is the sole pointer to a memory object graph. An Owner pointer normally does not have a scope attribute. If a pointer with the scope attribute is initialized with an expression not derived from a tracked pointer, it is an Owner.
If an Owner pointer is assigned to another Owner pointer, the former enters the Undefined state.
- Borrowed
- A Borrowed pointer is one that temporarily becomes the sole pointer to a memory object graph. It enters that state via assignment from an owner pointer, and the owner then enters the Lent state until after the last use of the borrowed pointer.
A Borrowed pointer must have the scope attribute and must be a pointer to mutable.
- Readonly
- A Readonly pointer acquires its value from an Owner. While the Readonly pointer is live, only Readonly pointers can be acquired from that Owner. A Readonly pointer must have the scope attribute and also must not be a pointer to mutable.
Lifetimes
The lifetime of a Borrowed or Readonly pointer value starts when it is first read (not when it is initialized or assigned a value), and ends at the last read of that value.
This is also known as Non-Lexical Lifetimes.
Pointer State Transitions
A pointer changes its state when one of these operations is done to it:
- storage is allocated for it (such as a local variable on the stack), which places the pointer in the Undefined state
- initialization (treated as assignment)
- assignment - the source and target pointers change state based on what states they are in and their types and storage classes
- passed to an out function parameter (changes state after the function returns), treated the same as initialization
- passed by ref to a function parameter, treated as an assignment to a Borrow or a Readonly depending on the storage class and type of the parameter
- returned from a function
- it is passed by value to a function parameter, which is treated as an assignment to that parameter.
- it is implicitly passed by ref as a closure variable to a nested function
- the address of the pointer is taken, which is treated as assignment to whoever receives the address
- the address of any part of the memory object graph is taken, which is treated as assignment to whoever receives that address
- a pointer value is read from any part of the memory object graph, which is treated as assignment to whoever receives that pointer
- merging of control flow reconciles the state of each variable based on the states they have from each edge
- Added -preview=in to make the in storage class mean scope const.
Although technically defined to be const scope, the in storage class has never been implemented as such until this preview switch. With the implementation now done, in should be the storage class of choice for purely input function parameters.
Without -preview=in, these two declarations are equivalent:
void fun(in int x); void fun(const int x);
With -preview=in, these two declarations are equivalent:
void fun(in int x); void fun(scope const int x);
- Validate printf and scanf (variants too) arguments against format specifiers
Follows the C99 specification 7.19.6.1 for printf and 7.19.6.2 for scanf.
For printf, it takes a generous, rather than strict, view of compatiblity. For example, an unsigned value can be formatted with a signed specifier.
For scanf, it takes a strict view of compatiblity.
Diagnosed incompatibilities are:
- incompatible sizes which will cause argument misalignment
- deferencing arguments that are not pointers
- insufficient number of arguments
- struct arguments
- array and slice arguments
- non-pointer arguments to s specifier
- non-standard formats
- undefined behavior per C99
Per the C Standard, extra arguments are ignored.
No attempt is made to fix the arguments or the format string.
In order to use non-Standard printf/scanf formats, an easy workaround is:
printf("%k\n", value); // error: non-Standard format k
const format = "%k\n"; printf(format.ptr, value); // no error
Most of the errors detected are portability issues. For instance,
string s; printf("%.*s\n", s.length, s.ptr); printf("%d\n", s.sizeof); ulong u; scanf("%lld%*c\n", &u);
should be replaced with:
string s; printf("%.*s\n", cast(int) s.length, s.ptr); printf("%zd\n", s.sizeof); ulong u; scanf("%llu%*c\n", &u);
Printf-like and scanf-like functions are detected by prefixing them with pragma(printf) for printf-like functions or pragma(scanf) for scanf-like functions.
In addition to the pragma, the functions must conform to the following characteristics:
- be extern (C) or extern (C++)
- have the format parameter declared as const(char)*
- have the format parameter immediately precede the ... for non-v functions, or immediately precede the va_list parameter (which is the last parameter for "v" variants of printf and scanf)
which enables automatic detection of the format string argument and the argument list.
Checking of "v" format strings is not implemented yet.
- Environment variable SOURCE_DATE_EPOCH is now supported
The environment variable SOURCE_DATE_EPOCH is used for reproducible builds. It is an UNIX timestamp (seconds since 1970-01-01 00:00:00), as described here. DMD now correctly recognize it and will set the __DATE__, __TIME__, and __TIMESTAMP__ tokens accordingly.
Limitations
Being a prototype, there are a lot of aspects not dealt with yet, and won't be until the prototype shows that it is a good design.
Bugs
Expect lots of bugs. Please report them to bugzilla and tag with the "ob" keyword. It's not necessary to report the other limitations that are enumerated here.
Class References and Associative Array References are not Tracked
They are presumed to be managed by the garbage collector.
Borrowing and Reading from Non-Owner Pointers
Owners are tracked for leaks, not other pointers. Borrowers are considered Owners if they are initialized from other than a pointer.
@live void uhoh() { scope p = malloc(); // p is considered an Owner scope const pc = malloc(); // pc is not considered an Owner } // dangling pointer pc is not detected on exit
It doesn't seem to make much sense to have such pointers as scope, perhaps this can be resolved by making such an error.
Pointers Read/Written by Nested Functions
They're not tracked.
@live void ohno() { auto p = malloc(); void sneaky() { free(p); } sneaky(); free(p); // double free not detected }
Exceptions
The analysis assumes no exceptions are thrown.
@live void leaky() { auto p = malloc(); pitcher(); // throws exception, p leaks free(p); }
One solution is to use scope(exit):
@live void waterTight() { auto p = malloc(); scope(exit) free(p); pitcher(); }
or use RAII objects or call only nothrow functions.
Lazy Parameters
These are not considered.
Quadratic Behavior
The analysis exhibits quadratic behavior, so keeping the @live functions smallish will help.
Mixing Memory Pools
Conflation of different memory pools:
void* xmalloc(size_t); void xfree(void*); void* ymalloc(size_t); void yfree(void*); auto p = xmalloc(20); yfree(p); // should call xfree() instead
is not detected.
This can be mitigated by using type-specific pools:
U* umalloc(); void ufree(U*); V* vmalloc(); void vfree(V*); auto p = umalloc(); vfree(p); // type mismatch
and perhaps disabling implicit conversions to void* in @live functions.
Variadic Function Arguments
Arguments to variadict functions (like printf) are considered to be consumed. While safe, this doesn't seem to be very practical, and will likely need revisiting.
Runtime changes
- Added TypeInfo_Class/TypeInfo_Interface.isBaseOf that works like C#/Java isAssignableFrom.
TypeInfo_Class.isBaseOf returns true if the argument and the receiver are equal or if the class represented by the argument inherits from the class represented by the receiver. This is called isBaseOf instead of isAssignableFrom to avoid confusion for classes that overload opAssign and so may allow assignment from classes outside their inheritance hierarchy and to match existing terminology in the D runtime. TypeInfo_Interface.isBaseOf is similar with the addition that the argument may be either TypeInfo_Class or TypeInfo_Interface.
class ClassA {} class ClassB : ClassA {} auto a = new ClassA(), b = new ClassB(); assert(typeid(a).isBaseOf(typeid(a))); assert(typeid(a).isBaseOf(typeid(b))); assert(!typeid(b).isBaseOf(typeid(a)));
- Add core.memory.pageSize and minimumPageSize.
pageSize contains the size of a system page in bytes.
import core.memory : pageSize; ubyte[] buffer = new ubyte[pageSize];
minimumPageSize contains the minimum size of a system page in bytes.
This is a compile time, platform specific value. This value might not be accurate, since it might be possible to change this value. Whenever possible, please use pageSize instead, which is initialized during runtime.
The minimum size is useful when the context requires a compile time known value, like the size of a static array: ubyte[minimumPageSize] buffer.
import core.memory : minimumPageSize; ubyte[minimumPageSize] buffer;
Library changes
- Add Date.isoWeekYear and Date.fromISOWeek in std.datetime.date
It is now possible to convert from the ISO 8601 week calendar into the Gregorian calendar which is used by Date and DateTime.
Dates are constructed from the year in the ISO week calendar, the week number and a day of week. Date.fromISOWeek(2020, 11, DayOfWeek.mon) will result in Date(2020, 3, 9).
As the year in the Gregorian calendar and the year in the ISO week calendar are not always the same there is a new .isoWeekYear property to get the year of the Date object in the ISO week calendar. If you convert between them often, consider using .isoWeekAndYear to compute both week number and year in one step.
- Deprecated module std.xml
The module std.xml has been deprecated. Any code that still needs it can use UndeaD instead. For parsing xml files, we recommend to use the dub package dxml.
- The deprecated aliases in std.digest.digest were removed
They were deprecated since 2.076.1 and have now been removed. Import std.digest or its submodules instead.
Additionally the deprecation cycle for std.digest.digest was started and the module will be removed in 2.101.
Dub changes
- Builds dynamicLibrary targets as dynamic libraries instead of static libraries.
Dub will no longer build dynamicLibrary targetType's as staticLibrary.
Except for x86_omf. This has been disabled due to numerous issues that will lead this to not doing what is expected of it.
No compiler or linker flags have been added at this time, you will need to specify the relevant flag to get the compiler to link dynamically against Phobos.
- The $DUB_BUILD_PATH variable was added
The $DUB_BUILD_PATH variable is now defined inside the postBuildCommands section. It contains the absolute path in which the package was built, and can be used to copy by-products of the build process to their intended locations.
For example, if an executable exports symbols, you will want to make the resulting import library and symbols export file available somewhere. That can be done with a dub.json section like this:
"postBuildCommands-windows": [ "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.lib $PACKAGE_DIR\\lib" "copy /y $DUB_BUILD_PATH\\$DUB_TARGET_NAME.exp $PACKAGE_DIR\\lib" ],
- Command environment variable substitution changed
Now users can use the documented predefined variables inside custom command directives without the need for a wrapper shell script.
Before this would have failed:
"preBuildCommands": ["$DC -run foo.d"]
unless DC was defined as environment variable outside DUB.
It was before possible to run a script that used the $DC environment variable or on POSIX escape the $ with $$DC to make the shell substitute the variable. These workarounds are no longer needed now.
API change: none of the different command directives are no longer substituted with the process environment variables. You now access the raw commands as provided by the user in the recipe. dub describe has been adjusted and now also processes the predefined environment variables as well as the process environment variables.
List of all bug fixes and enhancements in D 2.093.0:
DMD Compiler regressions
- Bugzilla 19550: [REG 2.078] Massive compiler backend slowdown
- Bugzilla 20626: ICE when using typeof of unittest symbol without -unittest flag
- Bugzilla 20830: Segfault for multiple duplicate interfaces
- Bugzilla 20833: Template members prevent __traits(getOverloads) from working properly
- Bugzilla 20885: pointer rejected for the variable declared in a if condition
- Bugzilla 20890: parameter corruption when other parameter is a static array of length 1
- Bugzilla 20893: [REG 2.087] 32-bit arithmetic goes wrong
DMD Compiler bugs
- Bugzilla 12504: Wrong 'cannot cover index range' error message
- Bugzilla 12520: Comparing two TypeTuples with == does not compile for no arguments
- Bugzilla 15235: inline asm: silent ICE (segfault) in asm_add_exp()
- Bugzilla 16971: Misleading error messages "break is not inside scope(exit) bodies" "continue is not inside scope(exit) bodies"
- Bugzilla 19344: Enum member UDAs & getUDAs throwing an error
- Bugzilla 19728: AliasSeq in UDA errors
- Bugzilla 20093: __traits(getAttributes) Error: cannot form tuple of tuples
- Bugzilla 20183: Assigning statement scope of struct literal or temporary to variable with longer lifetime
- Bugzilla 20410: ReplaceTypeUnless replaces enums with their basetype
- Bugzilla 20709: Segmentation fault when importing nonexistent type
- Bugzilla 20710: ICE when statically accessing struct member containing empty array
- Bugzilla 20719: Self referential struct definition causes stack overflow
- Bugzilla 20747: @live tracking of non-pointer owners not done
- Bugzilla 20758: __traits(getAttributes) as template argument results in broken template instances
- Bugzilla 20771: va_arg doesn't work for structs with postblits
- Bugzilla 20772: va_arg doesn't work for structs with copy constructors
- Bugzilla 20775: Missing fail compilation test for passing types that need destruction
- Bugzilla 20780: Function parameter UDA not accepted in nested function declarations
- Bugzilla 20789: is(T: U) doesn't exclude deprecated alias calls with -de
- Bugzilla 20800: Error: cannot implicitly convert expression with bad diagnostic.
- Bugzilla 20824: error messages generated by dmd build script can be prefixed with a non-standard "ERROR:"
- Bugzilla 20825: the filename of the error messages generated by dmd build.d script miss the "src/" part of the path
- Bugzilla 20835: Enum member attributes being evaluated in wrong scope.
- Bugzilla 20840: No deprecation when using template from deprecated selective import
- Bugzilla 20842: Structs with disabled default/copy ctors can't be initialized
- Bugzilla 20861: Interface implementations are not checked when code gen is skipped
- Bugzilla 20875: [REG2.087.1] Enum template specialization ignored
- Bugzilla 20894: ICE: passing a member template mixin identifier as alias argument
- Bugzilla 20903: seg fault on long signed divide overflow
- Bugzilla 20906: unnecessary divide-by-zero errors when constant folding short circuits
- Bugzilla 20909: .offsetof fails on forward reference of field
- Bugzilla 20915: __traits(allMembers) results include custom version identifiers, which is unusable
- Bugzilla 20919: DMD crash when '__traits' prints error involving a Parameter
- Bugzilla 20923: Redefinition of 'size_t' is affecting TypeStruct functions
- Bugzilla 20989: Checking array.ptr causes safety error with -checkaction=context
DMD Compiler enhancements
- Bugzilla 20744: Using __parameters result in function definition causes wrong lookup
- Bugzilla 20791: extern(C++
) should allow a trailing comma - Bugzilla 20796: protection attribute package(x.y) does not bind to one of ancestor packages of module x.y when declared in x/y/package.d
Phobos regressions
- Bugzilla 20943: std.algorithm.setops.cartesianProduct fails for ranges with @system popFront
Phobos bugs
- Bugzilla 9298: some std.math functions not implemented for Win64
- Bugzilla 20426: doesPointTo with void[N] fails
- Bugzilla 20751: SortedRange with ref predicate parameters fails
- Bugzilla 20782: std.conv.to can't convert string to const enum
- Bugzilla 20783: std.string.lastIndexOf doesn't work correctly in CTFE
- Bugzilla 20785: std.file.setTimes: on macOS use setattrlist to avoid truncating timestamp precision to microseconds
- Bugzilla 20836: std.math: reorder declarations from most visible to least
- Bugzilla 20850: Can't assign enum of Tuple
- Bugzilla 20874: std.json.assign requires '@safe' and 'pure'
- Bugzilla 20928: Overloaded opIndex confuses MapResult
Phobos enhancements
- Bugzilla 19525: Duration is not usable with zero-arg std.algorithm.sum
- Bugzilla 20496: chunkby should support ref predicates
- Bugzilla 20869: std.algorithm.mutation : move is overly trusting of opPostMove
- Bugzilla 20887: Improve speed of std.digest.digest!(Hash, Range) on non-array ranges
Druntime bugs
- Bugzilla 18011: core.sys.condition cannot be used as shared
- Bugzilla 20760: checkaction=context doesnt print floating point numbers correctly
- Bugzilla 20763: checkaction=context does not format pointers
- Bugzilla 20767: [DIP1014] __move_post_blt must only recursively call itself on a struct's fields not all members
- Bugzilla 20768: [DIP1014] __move_post_blt must recursively call itself on static arrays whose elements are structs or static arrays that recursively contain structs
- Bugzilla 20832: Fix ioctl request for TCSETS2
- Bugzilla 20852: core.sys.posix.sys.wait missing definitions on FreeBSD
Druntime enhancements
- Bugzilla 20746: Change LCG in garbage collector treap to use full 64 bits of state instead of 48
- Bugzilla 20787: Add module core.sys.darwin.sys.attr with getattrlist, setattrlist, searchfs, and related definitions
- Bugzilla 20844: DMD compiler should take care of data alignment, after seeing the 'cas' call
- Bugzilla 20859: Add overloads of core.sync.rwmutex.ReadWriteMutex.Reader/Writer.tryLock that take a timeout duration
dlang.org enhancements
- Bugzilla 20882: Outdated examples in the documentation (std.stdio)
Tools enhancements
- Bugzilla 13345: rdmd --eval doesn't support args
Installer bugs
- Bugzilla 20826: CI breakage: create_dmd_release attempts to copy the complete dmd repo.
Contributors to this release (55)
A huge thanks goes to all the awesome people who made this release possible.
- Adam D. Ruppe
- aG0aep6G
- Alexandru Militaru
- Andrei Alexandrescu
- Anton Oks
- Atila Neves
- Bastiaan Veelo
- Ben Jones
- blackbird
- Boris Carvajal
- BthereDthat
- Christian Koestlin
- Cristian Creteanu
- Denis Feklushkin
- dkorpel
- drug007
- Ernesto Castellotti
- Florian
- guai
- Hiroki Noda
- Iain Buclaw
- Jacob Carlborg
- John Colvin
- Kazuya Takahashi
- Luhrel
- Manu Evans
- Martin Kinkelin
- Martin Nowak
- Mathias Lang
- Mathis Beer
- Mike Parker
- MoonlightSentinel
- Nathan Sashihara
- Nicholas Wilson
- Nick Treleaven
- Nils Lankila
- Patrick Schlüter
- Paul Backus
- Per Nordlöw
- Petar Kirov
- Pierre Grimaud
- Rainer Schuetze
- Razvan Nitu
- Richard Manthorpe
- Sebastian Wilzbach
- Sergei Akhmatdinov
- Simen Kjærås
- Steven Schveighoffer
- Tomoya Tanjo
- Vladimir Panteleev
- Walter Bright
- Walter Waldron
- welkam
- Witold Baryluk
- wolframw