Change Log: 2.087.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
- Turn deprecation into error for privately imported symbols inside aggregate declarations
- Generated opEquals takes precedence over aliased this member opEquals
- Copy Constructor
- HexString literals are now obsolete
- Turn deprecation into error for selectively imported symbols in imported modules.
- Function literals can now return by reference
- New command-line option -lowmem to reduce compiler memory requirements
- Enable private member access for traits
Runtime changes
Library changes
Installer changes
Dub changes
List of all upcoming bug fixes and enhancements in D 2.087.0.
Compiler changes
- Turn deprecation into error for privately imported symbols inside aggregate declarations
With this release DMD will issue an error when a symbol that is privately imported in the scope of an aggregate declaration is used as a member of the aggregate outside of the module where the aggregate is defined. Example:
// a.d class Foobar { int a; this(int a) { this.a = a; } static int smeth() { return 1; } } void fun() {} // b.d struct AST { import a; } // c.d void main() { import b; AST.Foobar t; // triggered a deprecation, but will now trigger an error AST.Foobar.smeth(); // error AST.fun(); // error }
- Generated opEquals takes precedence over aliased this member opEquals
Before this patch, if a struct had an aliased this member that defined an opEquals method, the aliased this opEquals would have been preferred instead of the struct one:
struct A { int a, b; bool opEquals(ref A rhs) const { return a == rhs.a && b == rhs.b; } } struct B { int n; A a; alias a this; } void main() { B a, b; assert(a == b); // rewritten to a.a.opEquals(b.a) }
Although the compiler generates an opEquals for struct B that does member-wise equality comparison (==), the aliased this one is wrongfully preferred.
This patch corrects this issue by always choosing the defined opEquals (even if it is generated by the compiler) instead of the alias this one. If the behavior prior to this patch is desired, an explicit opEquals needs to be provided.
References: [1] https://issues.dlang.org/show_bug.cgi?id=16657 [2] https://github.com/dlang/dmd/pull/9289 [3] https://github.com/dlang/dlang.org/pull/2593
- Copy Constructor
With this release, the D language compiler implements the full functionality of the copy constructor described extensively in this DIP [1].
Copy constructors are used to initialize a struct instance from another struct of the same type.
A constructor declaration is a copy constructor declaration if and only if it is a constructor declaration that takes only one non-default parameter by reference that is of the same type as typeof(this), followed by any number of default parameters:
struct A { this(ref return scope A rhs) {} // copy constructor this(ref return scope const A rhs, int b = 7) {} // copy constructor with default parameter }
The copy constructor is type checked as a normal constructor.
If a copy constructor is defined, implicit calls to it will be inserted in the following situations:
- When a variable is explicitly initialized:
struct A { this(ref return scope A rhs) {} } void main() { A a; A b = a; // copy constructor gets called }
- When a parameter is passed by value to a function:
- When a parameter is returned by value from a function and Named Returned Value Optiomization (NRVO) cannot be performed:
- S does not explicitly declare any copy constructors;
- S defines at least one direct member that has a copy constructor, and that member is not overlapped (by means of union) with any other member.
- HexString literals are now obsolete
HexString literals are obsolete.
Prior to this release, usage of hex string literals would emit a deprecation warning. Starting with this release they will emit an error.
Use std.conv.hexString instead.
- Turn deprecation into error for selectively imported symbols in imported modules.
With this release DMD will issue an error when a symbol that is privately and selectively imported in module A is accessed in module B that imports module A non-selectively. Example:
// a.d import fun : foo; // b.d import a; void main() { foo(); // deprecation up until now; error from now on }
To make the above code compile, the import in a.d needs to be made public.
- Function literals can now return by reference
Prior to this release, there was no way to declare a function that would return a reference by using an anonymous function.
(It was possible to return a pointer but it's not worth mentioning.)Here this function returns by value:
alias fn = () => a += 2;
In order to return by reference, we needed to define a named function to assign from:
ref int func() // a static or non-nested function to mimic a `function` literal { // or a non-static nested function to mimic a `delegate` literal return a += 2; } alias fn = func;
Now it's possible to use the ref keyword to indicate a return by reference:
function ref () { return x; } // `=>` shorthand is there too delegate ref () { return x; } ref () { return x; }
For example:
int x = 1; alias add2 = ref () => x += 2; add2() += 7; // add2 as a lvalue assert(x == 10);
- New command-line option -lowmem to reduce compiler memory requirements
It enables the garbage collector for the compiler, trading compile times for (in some cases, significantly) less memory requirements.
E.g., compiling DMD's test tool d_do_test (dmd -c [-lowmem] test/tools/d_do_test.d) requires about 75% less memory (~1,630 MB -> 410) at the cost of a runtime increase by ~30% (~4.8 secs -> 6.3).
- Enable private member access for traits
The following traits can now access non-public members:
- getMember
- getOverloads
This fixes a long-standing issue in D where the allMembers trait would correctly return non-public members but those non-public members would be inaccessible to other traits.
See BugZilla issue 15371
struct A { this(ref return scope A another) {} } void fun(A a) {} void main() { A a; fun(a); // copy constructor gets called }
struct A { this(ref return scope A another) {} } A fun() { A a; return a; // NRVO, no copy constructor call } A a; A gun() { return a; // cannot perform NRVO, rewrite to: return (A __tmp; __tmp.copyCtor(a)); } void main() { A a = fun(); A b = gun(); }
When a copy constructor is defined for a struct, all implicit blitting is disabled for that struct:
struct A { int[] a; this(ref return scope A rhs) {} } void fun(immutable A) {} void main() { immutable A a; fun(a); // error: copy constructor cannot be called with types (immutable) immutable }
The copy constructor can be overloaded with different qualifiers applied to the parameter (copying from a qualified source) or to the copy constructor itself (copying to a qualified destination):
struct A { this(ref return scope A another) {} // 1 - mutable source, mutable destination this(ref return scope immutable A another) {} // 2 - immutable source, mutable destination this(ref return scope A another) immutable {} // 3 - mutable source, immutable destination this(ref return scope immutable A another) immutable {} // 4 - immutable source, immutable destination } void main() { A a; immutable A ia; A a2 = a; // calls 1 A a3 = ia; // calls 2 immutable A a4 = a; // calls 3 immutable A a5 = ia; // calls 4 }
The inout qualifier may be applied to the copy constructor parameter in order to specify that mutable, const, or immutable types are treated the same:
struct A { this(ref return scope inout A rhs) immutable {} } void main() { A r1; const(A) r2; immutable(A) r3; // All call the same copy constructor because `inout` acts like a wildcard immutable(A) a = r1; immutable(A) b = r2; immutable(A) c = r3; }
A copy constructor is generated implicitly by the compiler for a struct S if all of the following conditions are met:
If the restrictions above are met, the following copy constructor is generated:
this(ref return scope inout(S) src) inout { foreach (i, ref inout field; src.tupleof) this.tupleof[i] = field; }
If the generated copy constructor fails to type check, it will receive the @disable attribute.
f an union S has fields that define a copy constructor, whenever an object of type S is initialized by copy, an error will be issued. The same rule applies to overlapped fields (anonymous unions).
A struct that defines a copy constructor is not a POD.
[1] https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1018.md
Runtime changes
- New module core.sync.event
This module provides a cross-platform interface for lightweight signaling of other threads. It can be used to start execution of multiple waiting threads simultaneously.
Library changes
- Fixed comparison bug in std.algorithm.comparison.levenshteinDistance
Previously the algorithm was allocating the amount of memory which was equal to the size of the biggest range, that is Ο(max(s.length, t.length)). This is now fixed to be Ο(min(s.length, t.length)). For more details see std.algorithm.comparison.levenshteinDistance.
- std.experimental.all has been moved to std
std.experimental.all allowed the convenient use of all Phobos modules with one import (import std.experimental.all;). With this release, this convenience module has been stabilized and moved to std. From now on, the convenience module can be accessed with import std;:
import std; void main() { 5f.iota.map!exp2.sum; // 31 }
Scripts and experimental code often use long and frequently changing lists of imports from the standard library.
With this release it is possible to use import std; for importing the entire standard library at once. This can be used for fast prototyping or REPLs:
import std; void main() { 6.iota .filter!(a => a % 2) // 1 3 5 .map!(a => a * 2) // 2 6 10 .tee!writeln // peek into the processed stream .substitute(6, -6) // 2 -6 10 .mean // (2 - 6 + 10) / 3 .reverseArgs!writefln("Sum: %.2f"); // 2 }
As before, symbol conflicts will only arise if a symbol with collisions is used. In this case, static imports or renamed imports can be used to uniquely select a specific symbol.
The baseline cost for import std; is less than half a second (varying from system to system) and work is in progress to reduce this overhead even further.
Installer changes
- The bundled LLD Linker has been upgraded to 8.0.0
The bundled LLD Linker on Windows binaries has been upgraded to 8.0.0.
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: ```json "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.087.0:
DMD Compiler regressions
- Bugzilla 19584: Illegal optimization: Shift-or -> imul
- Bugzilla 19631: Segfault on simple nested templated struct
- Bugzilla 19661: DMD 2.084.0 SIGSEGV in std.traits.isFunction
- Bugzilla 19758: (0x01 & 0xFF) == 0 by dmd 2.085.0(-m64) on Windows
- Bugzilla 19871: Copy constructor rejects valid code if default construction is disabled
- Bugzilla 19887: Segfault with void tuple default parameter
- Bugzilla 19901: importing export symbols causes link errors
- Bugzilla 19936: Deprecated alias get this falsely triggers on appending to array
DMD Compiler bugs
- Bugzilla 711: combining mixins and overriding causes inifite loops
- Bugzilla 1170: Cannot forward reference a type defined in a MixinStatement
- Bugzilla 4923: immutable module variables are modifiable in non-shared module constructors
- Bugzilla 6541: using synchronized on a templated method crashes the compiler
- Bugzilla 9029: Built-in types treated specially for alias parameters
- Bugzilla 10739: Struct defined by template mixin leads to order-sensitivity of declarations
- Bugzilla 12950: Lexer interprets UFCS on hex integer as hex float literal
- Bugzilla 13471: CTFE glitch when executing std.digest.crc.crc32Of() and checking the result with enforce(). (keyword: uninitialized variable)
- Bugzilla 13819: ICE: backend\cg87.c with -O: "a % 2 != 0" for a double
- Bugzilla 13848: overlapping initialization for r
- Bugzilla 17141: Type Inference Incorrectly Converts Characters to Integers
- Bugzilla 17258: Pass by name doesn't work reliably and can sometimes lead to memory corruption
- Bugzilla 17793: [ICE] Internal error: ddmd/backend/cod1.c 3976 using simd.double4
- Bugzilla 18772: [ICE] Internal error: dmd\backend\cgcod.c 607 no optimizations
- Bugzilla 18784: Segfault due to dmd codegen interfacing with C++
- Bugzilla 18794: Compiling with -O causes runtime segfault
- Bugzilla 18958: extern(C++) wchar, dchar mangling not correct
- Bugzilla 19002: __FUNCTION__ and __PRETTY_FUNCTION__ cannot be used as C string literals
- Bugzilla 19234: betterC TypeInfo error when using slice copy on Structs
- Bugzilla 19386: Destructor not called when constructed inside if condition, leading to memory leak
- Bugzilla 19557: extern(C++, ns) and extern(C++, class) interact weird
- Bugzilla 19713: dmd crashes generating code for C++ template function
- Bugzilla 19754: cast() sometimes yields lvalue, sometimes yields rvalue
- Bugzilla 19813: Generated bt instruction seg faults, high 32 bits of register is garbage
- Bugzilla 19814: Nested code blocks in Ddoc break formatting
- Bugzilla 19825: Memory corruption involving lazy variadic, stdio and json
- Bugzilla 19829: __traits(isSame) returns true for some non-local delegate lambdas even when they are different
- Bugzilla 19831: throw/catch in scope(exit) crashes with illegal instruction
- Bugzilla 19857: Name mangling mismatch when compiling with -dip1000
- Bugzilla 19870: Generated Copy Constructor disables default construction
- Bugzilla 19881: Escaping reference to local through return scope with -dip1000 and @safe
- Bugzilla 19888: default parameters in templates with tuple parameters+defaults are thrown away
- Bugzilla 19890: ICE: Segmentation fault with negative array size
- Bugzilla 19891: Confusing error message for auto ref parameters with default values
- Bugzilla 19893: extern(C++, "ns") should count as module scope for version declarations
- Bugzilla 19895: Floating point exception casting zero length array
- Bugzilla 19897: dinterpret.d:6439: Internal Compiler Error: null field
- Bugzilla 19898: ICE: in sizemask at dmd/mtype.d(2563): Assertion failure
- Bugzilla 19905: Floating point .init should be bitwise identical to .nan
- Bugzilla 19911: ICE: Segmentation fault with struct object and variadic function
- Bugzilla 19912: [module] No implicit import of object module when an object declaration exists.
- Bugzilla 19913: ICE: Segmentation fault with mixin and enum
- Bugzilla 19914: ICE: Segmentation fault with mixin and templated class
- Bugzilla 19915: ICE: Segmentation fault with alias and templated class
- Bugzilla 19920: __trait(parent, ...) broken with extern(C++,"ns") nested in scopes
- Bugzilla 19922: ICE: Segmentation fault with typeid()
- Bugzilla 19923: ICE: typesem.d(3809): Assertion failure with .classinfo
- Bugzilla 19941: [ICE] Segmentation fault in ImplicitConvTo::visit(AddrExp*) at dmd/dcast.d(980)
- Bugzilla 19942: [ICE] Segmentation fault in resolvePropertiesX at dmd/expressionsem.d:1112
- Bugzilla 19954: ICE: Casting AliasSeq to array and passing to a function
- Bugzilla 19955: [ICE] Segmentation fault in StatementSemanticVisitor::visit(SwitchStatement*) at dmd/statementsem.d:2558
- Bugzilla 19971: wrong string literals in "cannot pass argument" errors
- Bugzilla 19995: parameter attributes are accepted in parameter-less functions
DMD Compiler enhancements
- Bugzilla 10665: The documentation produced by ddoc should clearly list all public imports of a module
- Bugzilla 16002: Add __traits(isModule) and __traits(isPackage)
- Bugzilla 16020: Allow AliasDeclarationY to express function types
- Bugzilla 19856: [aApplycd2]: foreach (int) doesn't work on BigEndian targets
Phobos regressions
- Bugzilla 17358: [REG 2.074.0] std.stdio.File.lockingTextWriter.put no longer accepts chains of characters
- Bugzilla 19740: Incorrect result of BigInt * BigInt
Phobos bugs
- Bugzilla 11061: std.variant.Variant equality comparison always returns false for static array literals.
- Bugzilla 19226: std.typecons.Nullable(T, T nullValue) doesn't fully handle non-self-equal nullValue
- Bugzilla 19781: etc.c.zlib should be @nogc
- Bugzilla 19836: Excessive probability of UUID collisions in std.uuid.randomUUID
- Bugzilla 19837: std.random.isUniformRNG(Rng, ElementType) should not require Rng.front to be annotated @property
- Bugzilla 19850: double nested joiner .back falsely thinks the range is empty
- Bugzilla 19883: Cyclic constructor call for BigInt(dstring)
- Bugzilla 19899: std.bitmanip.bitsSet should accept const arguments
- Bugzilla 19939: std.format %13,3.2f does not count width correctly
Phobos enhancements
- Bugzilla 6657: dotProduct overload for small fixed size arrays
- Bugzilla 13965: More handy schwartzSort
- Bugzilla 19513: Use sched_getaffinity(2) to get the number of CPU cores if available
- Bugzilla 19892: Add CTFE support for std.bitmanip: nativeToBigEndian, bigEndianToNative, littleEndianToNative, nativeToLittleEndian
Druntime regressions
- Bugzilla 19701: undefined reference to `_D6object__T6hashOf
Druntime bugs
- Bugzilla 17248: Multiple wrong function definitions in core.sys.windows.winldap (causing runtime issues)
- Bugzilla 19847: no GC memory above 4GB reported with --DRT-gcopt=profile:1
- Bugzilla 19861: core.cpuid reports the wrong number of threads
Contributors to this release (72)
A huge thanks goes to all the awesome people who made this release possible.
- aG0aep6G
- Andrei Alexandrescu
- Atila Neves
- Aurelien Fredouelle
- Aurélien Fredouelle
- Basile Burg
- Basile-z
- Bastiaan Veelo
- Ben Jones
- Ben Merritt
- Benjamin L. Merritt
- Cameron Ross
- Chalucha
- Chloé
- dan
- Dan Printzell
- David Gileadi
- Dibyendu Majumdar
- Diederik de Groot
- dukc
- Ernesto Castellotti
- Eugen Wissner
- FeepingCreature
- Flying-Toast
- Hiroki Noda
- Hiroo Ono
- hygonsoc
- Iain Buclaw
- Igor Stojković
- Ilya Yaroshenko
- Jacob Carlborg
- Jan Jurzitza
- Johannes Pfau
- John Colvin
- Jonathan M Davis
- Jonathan Marler
- Joseph Rushton Wakeling
- kinke
- Leandro Lucarella
- Les De Ridder
- look-at-me
- Manu Evans
- Marco de Wild
- Martin Kinkelin
- Martin Nowak
- Mathias Lang
- Mathis Beer
- MetaLang
- Mike Franklin
- Mike Parker
- Nathan Sashihara
- Nicholas Wilson
- Nick Treleaven
- Per Nordlöw
- Petar Kirov
- Q. F. Schroll
- Radu Racariu
- Rainer Schuetze
- Razvan Nitu
- Robert Schadek
- Sebastian Wilzbach
- shove
- shove70
- Simen Kjærås
- Spoov
- stefanos-baziotis
- Steven Schveighoffer
- Vladimir Panteleev
- Walter Bright
- Zevenberge
- سليمان السهمي (Suleyman Sahmi)
- سليمان السهمي (Suleyman Sahmi)