Change Log: 2.086.0
Download D 2.086.0
released May 04, 2019
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 bug fixes and enhancements in D 2.086.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:
- 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:
struct A { this(ref return scope A rhs) {} } void main() { A a; A b = a; // copy constructor gets called }
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:
- 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.
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
- 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
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
- Support of custom dub init type
Command dub init now supports custom dub packages for argument -t.
> dub init -n myPackage --format sdl -t custom-dub-init-dubpackage -- --foo=bar
Dub init will be invoked like before. The package custom-dub-init-dubpackage contains a sub package init-exec which will be invoked afterwards to create a custom package skeleton. Additional arguments could be passed e.g. -- --foo=bar.
- DUB will no longer use OPTLINK as default on Windows
DMD's OPTLINK has many limitations. Apart from long-standing issues in the underlying DigitalMars runtime, the maximum number of symbols is limited as well, which is why most big DUB libraries can't be compiled with OPTLINK for years. This has been a cause of grief and pain for many users and impacted the newcomer experience severly.
With this release, dub will no longer use OPTLINK as default on Windows, but use -m32mscoff (MSCOFF) on 32-bit Windows systems and -m64 (MSCOFF) on 64-bit Windows.
Users can still manually instruct dub to use OPTLINK with the --arch=x86 switch of dub:
> dub --arch=x86
- dub run will now automatically fetch a package if it's not found locally
Starting with this release, dub run <mypackage> makes sure that the package is available locally. This means that now a dub fetch <mypackage> is no longer required and all a user of a library needs to run your dub package is dub run:
> dub run gitcompatibledubpackage gitcompatibledubpackage wasn't found locally, but it's available online: ‐-- Description: Example of a DUB package also usable as git submodule. For DUB test suite. Version: 1.0.4 ‐-- Do you want to fetch gitcompatibledubpackage? [Y/n]:
An optional --yes (-y) flag is provided to confirm fetching non-interactively:
> dub run --yes gitcompatibledubpackage gitcompatibledubpackage wasn't found locally, but it's available online: ‐-- Description: Example of a DUB package also usable as git submodule. For DUB test suite. Version: 1.0.4 ‐-- Fetching gitcompatibledubpackage 1.0.4... Building package gitcompatibledubpackage in /home/seb/.dub/packages/gitcompatibledubpackage-1.0.4/gitcompatibledubpackage/ Performing "debug" build using dmd for x86_64. gitcompatibledubpackage 1.0.4: building configuration "exe"... Linking... Running ../../.dub/packages/gitcompatibledubpackage-1.0.4/gitcompatibledubpackage/gitcompatibledubpackage Hello DUB
An optional --non-interactive (-n) flag is provided to skip searching online packages:
> dub run --non-interactive gitcompatibledubpackage Failed to find a package named 'gitcompatibledubpackage'.
If one wants to run a specific version of a package, it can be passed to dub run too:
> dub run gitcompatibledubpackage@1.0.3 Fetching gitcompatibledubpackage 1.0.3... Building package gitcompatibledubpackage in /home/seb/.dub/packages/gitcompatibledubpackage-1.0.3/gitcompatibledubpackage/ Performing "debug" build using dmd for x86_64. gitcompatibledubpackage 1.0.3: building configuration "exe"... Linking... Running ../../.dub/packages/gitcompatibledubpackage-1.0.3/gitcompatibledubpackage/gitcompatibledubpackage Hello DUB
- Remove dub list-installed command
dub list-installed command was deprecated and renamed to list at in 2013.
- DUB uses single API requests to upgrade/resolve dependencies.
dub now uses single API request to upgrade/resolve dependencies. For more details, see pull #1366.
List of all bug fixes and enhancements in D 2.086.0:
DMD Compiler regressions
- Bugzilla 17684: [REG 2.062] static alias this bug or incomplete implementation?
- Bugzilla 18810: root/ctfloat depends upon backend
- Bugzilla 19519: cannot determine length of static array at compile time
- Bugzilla 19691: ICE on null default value for struct parameter in constructor
- Bugzilla 19722: botched implementation of semantic3Errors causes compiler assert fail
- Bugzilla 19774: wrong code caused by opIndex
- Bugzilla 19778: ICE when accessing empty array at compile time
- Bugzilla 19782: alias this appends null instead of inner/aliased element to array
- Bugzilla 19804: fails to compile with fixes size array T[1]... argument
- Bugzilla 19822: 2.086 regression wrt. union initializers
- Bugzilla 19833: The member as template cannot be acquired by getMember
- Bugzilla 19840: Ice in e2ir.d visit(CastExp) assert(false, "This case should have been rewritten to __ArrayCast in the semantic phase");
DMD Compiler bugs
- Bugzilla 5050: No way to declare delegates with ref return
- Bugzilla 10806: Interface covariance for more than one interface at once also broken
- Bugzilla 11934: Allow ref in foreach over range iff front returns by ref
- Bugzilla 15875: case of undetected circular reference in function parameter
- Bugzilla 17285: Segfault when types are used in array literals
- Bugzilla 17289: With Xcode 8.3 linker, warnings of "pointer not aligned"
- Bugzilla 17290: DMD crash due to circular reference in function return type
- Bugzilla 17651: Segfault when parsing Ddoc ESCAPES macro
- Bugzilla 18573: cast(void) leads to floating point return value not being popped from FPU stack
- Bugzilla 19051: Undefined functions Set/GetWindowLongPtr in mingw libs
- Bugzilla 19099: Struct with field that has postblit or destructor makes struct assignable
- Bugzilla 19442: multiple argument string mixin dont support char literals
- Bugzilla 19463: DIP1008 - _d_newclass is called instead of _d_newThrowable
- Bugzilla 19540: ICE when using typeof(new class {}) as default value for template parameter
- Bugzilla 19563: extern(C++) Incorrect ABI passing small struct
- Bugzilla 19569: overload resolution not right?
- Bugzilla 19658: C++ enum mangling is wrong on Windows for other integer types
- Bugzilla 19679: variable escapes unnoticed when referenced in function called from function whose address is taken
- Bugzilla 19688: [ICE] Default function argument concatenation crashes DMD
- Bugzilla 19717: case of segfault due to undetected forward reference
- Bugzilla 19719: Debugging string mixins using -mixin doesn't work
- Bugzilla 19731: auto struct methods whose address is taken don't test invariants
- Bugzilla 19734: isDataseg returns true for non-static declarations
- Bugzilla 19735: Error: variable extern symbols cannot have initializers
- Bugzilla 19744: Confusing error message when annotating a non-member function with return
- Bugzilla 19747: No debug line info for code in scope(exit)
- Bugzilla 19775: multiple argument string mixin doesn't expand tuples
- Bugzilla 19797: File.seek() terminates ungracefully on incorrect origin for -m32mscoff and -m64
DMD Compiler enhancements
- Bugzilla 8065: No way to write function/delegate literals returning ref T
- Bugzilla 12330: array.reserve at compile time too
- Bugzilla 15361: Incomprehensible error message: function declaration without return type.
- Bugzilla 15371: __traits(getMember) should bypass the protection
- Bugzilla 16271: Should be able to express that a lambda returns by reference
- Bugzilla 16657: alias this interacts with generated opCmp and opEquals
- Bugzilla 18825: No syntax for function literal returning a reference
- Bugzilla 19441: alias this causes partial assignment
- Bugzilla 19809: override block affects passing lambda as argument
Phobos regressions
- Bugzilla 19777: [REG2.086a] SortedRange.opSlice is wrongly @trusted
Phobos bugs
- Bugzilla 18728: std.math.fdim does not handle nan correctly
- Bugzilla 19042: Chunking a padRight'ed range leads to range violations
- Bugzilla 19151: std.utf.toUTF16z() can not be used for LPWSTR
- Bugzilla 19681: std.range.padRight.popFront does not correctly adjust length
- Bugzilla 19689: large types cannot be moved
- Bugzilla 19751: std.stdio.File should not retry fclose after error
- Bugzilla 19799: templated string formatting fails with const Nullable!string
- Bugzilla 19806: phobos/std/uri.d: ietf link outdated
Phobos enhancements
- Bugzilla 15853: std.random save methods must be const
- Bugzilla 18806: minIndex should be able to take an input range but does not
- Bugzilla 19412: std.algorithm.cmp with default ordering can use memcmp for all size 1 unsigned types (instead of just char)
- Bugzilla 19686: sgn is too greedy
Druntime regressions
- Bugzilla 18530: [Reg 2.079] src/rt/tracegc.d(43): Deprecation: The delete keyword has been deprecated
- Bugzilla 19796: druntime PR#1982 broke array ops on double[] due to wrong assumption of integral element type
Druntime bugs
- Bugzilla 19810: destroy does not work for C++ classes without destructor
- Bugzilla 19830: core.memory.__delete destructs arrays of structs in the wrong order
dlang.org bugs
- Bugzilla 11161: Document the default struct equality comparison and operator overloading
- Bugzilla 19621: The specification is self-contradictory on immutability
Installer regressions
- Bugzilla 18522: [REG 2.079-b2] MinGW import libraries interfere with platform SDK
Contributors to this release (51)
A huge thanks goes to all the awesome people who made this release possible.
- aG0aep6G
- Ali Çehreli
- Andrea Fontana
- Andrei Alexandrescu
- Andy Kurnia
- Arun Chandrasekaran
- Basile Burg
- Basile-z
- Bastiaan Veelo
- Ben Jones
- Boris Carvajal
- Cameron Ross
- David Gileadi
- David Nadlinger
- Dejan Lekic
- Eduard Staniloiu
- Flying-Toast
- Hiroki Noda
- Iain Buclaw
- Ilya Yaroshenko
- Jacob Carlborg
- John Colvin
- Jon Degenhardt
- kinke
- lempiji
- look-at-me
- majiang
- Martin Kinkelin
- Martin Nowak
- Mathis Beer
- Mike Franklin
- Mike Parker
- Nathan Sashihara
- Nicholas Wilson
- Nick Treleaven
- Paul Backus
- Petar Kirov
- Radu Racariu
- Rainer Schuetze
- Razvan Nitu
- Sebastian Wilzbach
- Simen Kjærås
- Sönke Ludwig
- tibi77
- TJesionowski
- Vasniktel
- Vasyl Teliman
- Vladimir Panteleev
- Walter Bright
- XyjVam
- سليمان السهمي (Suleyman Sahmi)