Change Log: 2.081.0
Download D 2.081.0
released Jul 01, 2018
Compiler changes
- Deprecate allowing a constructor declaration in a static block
- Deprecate usage of this and super as types
- Implement DIP 1009 - Add Expression-Based Contract Syntax
- extern (C++) construction, destruction, operators and other mangling improvements
- Support for iterating template overloads
- __traits(getLinkage, ...) now works on structs, classes, and interfaces.
- Implicit catch statements will now result in an error
- Implicit comparison of different enums will now result in an error
- Implicit string concatenation will now result in an error
- IRETQ is now supported in inline assembler.
- Interfaces and classes can be used without the runtime if only static fields are utilized
- Specifying redundant storage classes will now result in a compiler error
Runtime changes
Library changes
List of all bug fixes and enhancements in D 2.081.0.
Compiler changes
- Deprecate allowing a constructor declaration in a static block
Before patch: The language specification states that a static constructor is defined using the construction "static this()". Defining a constructor inside a static block does not have any effect on the constructor. The following code samples do not affect the constructor in any way:
static: this() {}
static { this() {} }
The compiler does not issue any warning/error on the above code samples and generates a normal constructor which is not ran before the main() function. This leads to situations in which the compiler is not able to correctly indicate the problem:
class A { static { this() {} } this() {} } void main() { new A(); }
This code will result in an error message indicating that there is a multiple definition of the constructor this() which is a misleading message.
After patch: Whenever a constructor is encountered in a static context a deprecation message is issued stating that the static keyword does not have any effect on the constructor. The solution is to declare the constructor outside the static block either as a normal constructor or a static one (static this()).
- Deprecate usage of this and super as types
Prior to this release, this and super could be used as both data or types depending on the context. Starting with this release using this or super as a type will result in a compiler error.
class C { shared(this) x; // Deprecation: Using `this` as a type is deprecated. Use `typeof(this)` instead } class D : C { shared(super) a; // Deprecation: Using `super` as a type is deprecated. Use `typeof(super)` instead super b; // Deprecation: Using `super` as a type is deprecated. Use `typeof(super)` instead }
Use typeof(super) or typeof(this) instead.
class C { shared(typeof(this)) x; } class D : C { shared(typeof(super)) a; typeof(super) b; }
- Implement DIP 1009 - Add Expression-Based Contract Syntax
Expression-based contract syntax has been added: Contracts that consist of a single assertion can now be written more succinctly and multiple in or out contracts can be specified for the same function.
Example:
class C { private int x; invariant(x >= 0); // ... } int fun(ref int a, int b) in(a > 0) in(b >= 0, "b cannot be negative") out(r; r > 0, "return must be positive") out(; a != 0) { // ... }
- extern (C++) construction, destruction, operators and other mangling improvements
Many improvements have been made to the extern(C++) experience in this release cycle.
Mangling improvements include:
- Constructor/destructor mangling matches C++
- Compatible D style operators now mangle as C++ operators
- nullptr_t mangles correctly
- Various mangling bugs have been fixed
extern(C++) APIs that use nullptr_t can use typeof(null) on the D side:
alias nullptr_t = typeof(null); extern (C++) void fun(nullptr_t);
extern (C++) mangling of operators is working for all operators that are semantically equivalent. This list includes all instantiations of opUnary, opBinary, opAssign, opOpAssign, opCast, opEquals, opIndex, opCall. Two notable exceptions are opCmp, and C++ operator !, which don't have compatible implementations.
Mangling of extern (C++) class constructors and destructor are working.
This release also includes ABI fixes where destructors are now correctly added to the virtual table, and constructor/destructor calling semantics now match C++. With this, mixed-language class hierarchies are working, with construction/destruction being supported in either language.
- Support for iterating template overloads
__traits(getOverloads) has been extended to return template overloads when passed an optional parameter with a true value.
struct S { static int foo()() { return 0; } static int foo()(int n) { return 1; } static int foo(string s) { return 2; } enum foo(int[] arr) = arr.length; } alias AliasSeq(T...) = T; alias allFoos = AliasSeq!(__traits(getOverloads, S, "foo", true)); static assert(allFoos.length == 4); static assert(allFoos[0]("") == 2); static assert(allFoos[1]() == 0); static assert(allFoos[2](1) == 1); alias foo3 = allFoos[3]; static assert(foo3!([]) == 0);
- __traits(getLinkage, ...) now works on structs, classes, and interfaces.
It is now possible to detect the language ABI specified for a struct, class, or interface.
class MyClass {} extern (C++) struct MyCPPStruct {} extern (C++) interface MyCPPInterface {} extern (Objective-C) interface MyObjcInterface {} static assert(__traits(getLinkage, MyClass) == "D"); static assert(__traits(getLinkage, MyCPPStruct) == "C++"); static assert(__traits(getLinkage, MyCPPInterface) == "C++"); static assert(__traits(getLinkage, MyObjcInterface) == "Objective-C");
- Implicit catch statements will now result in an error
See the Deprecated Features for more information.
Implicit catch statements were deprecated in 2.072. Starting with this release, implicit catch statements will cause the compiler to emit an error.
import std.stdio; void main() { int[] arr = new int[](10); // This will throw a RangeError try { arr[42]++; } catch // Error: `catch` statement without an exception specification is deprecated; // use `catch(Throwable)` for old behavior { writeln("An error was caught and ignored"); } }
- Implicit comparison of different enums will now result in an error
See the Deprecated Features for more information.
Implicit comparison of different enums was deprecated in 2.075. Starting with this release, implicit comparison of different enums will cause the compiler to emit an error.
enum Status { good, bad } enum OtherStatus { ok, no } static assert(Status.good == OtherStatus.ok); // Error: Comparison between different enumeration types `Status` and `OtherStatus`; // If this behavior is intended consider using `std.conv.asOriginalType`
- Implicit string concatenation will now result in an error
See the Deprecated Features for more information.
Implicit string concatenation was deprecated in 2.072. Starting with this release, implicit string concatenation will cause the compiler to emit an error.
void main() { string s = "Hello" ", World!"; // Error: Implicit string concatenation is deprecated, use "" ~ "" instead }
- IRETQ is now supported in inline assembler.
IRETQ is the 64-bit version of the already supported IRET instruction. With its inclusion, it is now possible to write 64-bit interrupt service routines in pure D.
void isr() { asm { naked; // ... iretq; } }
- Interfaces and classes can be used without the runtime if only static fields are utilized
Prior to this release any attempt to use interfaces and/or classes without the runtime would result in compile-time errors due to the lack of TypeInfo. However, as long as classes are not instantiated there is no need for TypeInfo.
Beginning with this release the compiler will no longer emit errors about missing TypeInfo when using interfaces and/or classes as long as they are not instantiated and only shared static members are utilized.
Example 1
module object private alias extern(C) int function(char[][] args) MainFunc; private extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc) { return mainFunc(null); // assumes `void main()` for simplicity }
interface I { shared static int i; } class A : I { shared static int a; } class B : A { shared static int b; } void main() { B.b = B.a + B.i; }
dmd -conf= -defaultlib= main.d object.d -of=main size main text data bss dec hex filename 1867 1208 32 3107 c23 main
Non-shared static members can also be used, but will require a thread-local storage (TLS) implementation. For example, on Linux the TLS implementation is already supplied by the C runtime and C standard library, so, since dmd automatically calls gcc to link the final executable, it will automatically bring in the TLS implementation.
Example 2
module object private alias extern(C) int function(char[][] args) MainFunc; private extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc) { return mainFunc(null); // assumes `void main()` for simplicity }
interface I { static int i; } class A : I { static int a; } class B : A { static int b; } void main() { B.b = B.a + B.i; }
dmd -conf= -defaultlib= main.d object.d -of=main size main text data bss dec hex filename 2123 1296 28 3447 d77 main
Some platforms may require some TLS implementation code or some specialized build procedures to link in a TLS implementation.
This will hopefully reduce friction for those using D without the runtime, porting D to new platforms, or using D from other langauges, while enabling more features and idioms of D to be used in those use cases.
- Specifying redundant storage classes will now result in a compiler error
Specifying redundant storage classes was deprecated long ago and was originally scheduled to emit a compiler error beginning with the 2.068 release. That promise has been fulfilled with this release.
@safe void f() @safe {} // Error: redundant attribute `@safe`
Runtime changes
- Filenames and line numbers have been added to stacktraces on macOS
When an exception is throw and not caught, a stacktrace is printed. On Linux, FreeBSD and DragonFlyBSD this stacktrace includes the filenames and line numbers, if the application was built with debug info enabled. This feature has now been added to macOS.
This requires support from the compiler since debug info is stripped by the linker on macOS.
Example:
void bar() { throw new Exception("bar"); } void foo() { bar(); } void main() { foo(); }
Compiling the above code, with debug info enabled, by running: dmd -g main.d. When running the application it will produce an output similar to:
[email protected](3): bar main.d:3 void main.bar() [0x71afdfb] main.d:8 void main.foo() [0x71afe0c] main.d:13 _Dmain [0x71afd78]
- object.destroy() supports extern(C++) classes.
object.destroy() was crashing when called with an extern(C++) class. It now correctly destructs and resets the object to init.
- Add missing declarations to core.sys.darwin.mach.getsect
Declarations that were missing from mach-o/getsect.h has been added to core.sys.darwin.mach.getsect.
Library changes
- The deprecated std.c package has been removed.
Use the core.stdc package instead.
- The performance of std.algorithm.iteration.joiner has been improved
DMD
> dmd -O -inline -release ./joiner.d && ./joiner before.joiner = 57 secs, 834 ms, 289 μs, and 3 hnsecs new.joiner = 44 secs, 936 ms, 706 μs, and 5 hnsecs
LDC
> ldmd -O3 -release -inline joiner.d && ./joiner before.joiner = 5 secs, 180 ms, 193 μs, and 7 hnsecs new.joiner = 3 secs, 168 ms, 560 μs, and 6 hnsecs
The benchmark code can be found here.
- std.algorithm.mutation.remove now only accepts integral values or pair of integral values as offset
Previously, without being stated in the documentation, std.algorithm.remove used to accept any values as offset. This behavior was very error-prone:
import std.algorithm, std.stdio; [0, 1, 2, 3, 4].remove(1, 3).writeln; // 0, 2, 4 -- correct [0, 1, 2, 3, 4].remove([1, 3]).writeln; // 0, 3, 4 -- incorrect
With this release, using arrays as individual elements is no longer valid. std.typecons.tuple can be used to explicitly indicate that a range from start to stop (non-enclosing) should be removed:
import std.algorithm, std.stdio, std.typecons; [0, 1, 2, 3, 4].remove(tuple(1, 3)).writeln; // 0, 3, 4
However, only 2-tuples are allowed to avoid this un-intuitive scenario:
import std.algorithm, std.stdio, std.typecons; [0, 1, 2, 3, 4].remove(tuple(1, 3, 4)).writeln; // 0, 4?
- Changed semantics of std.math.{fmin,fmax} wrt. NaNs.
The semantics of std.math.fmin and std.math.fmax have been streamlined with the C functions: if one of the arguments is a NaN, return the other. This involves an additional std.math.isNaN check. Use std.algorithm.comparison.min and std.algorithm.comparison.max for the previous semantics performing a single comparison.
import std.math; assert(fmin(real.nan, 2.0L) == 2.0L); assert(fmin(2.0L, real.nan) == 2.0L); // previously: NaN assert(isNaN(fmin(real.nan, real.nan))); import std.algorithm.comparison; assert(min(real.nan, 2.0L) == 2.0L); assert(isNaN(min(2.0L, real.nan))); assert(isNaN(min(real.nan, real.nan)));
Dub changes
- DUB supports "customCachePaths" for providing read-only package paths
With this release DUB allows defining additional paths that contain packages in subfolders with the pattern "(name)-(version)/(name)/" by defining a "customCachePaths" field in /etc/dub/settings.json or ~/.dub/settings.json.
"customCachePaths" can be used to provide prebuilt DUB libraries (e.g. for distribution package maintainers).
List of all bug fixes and enhancements in D 2.081.0:
DMD Compiler regressions
- Bugzilla 18068: No file names and line numbers in stack trace
- Bugzilla 18821: DMD segfault when doing unsafe operation outside of any function
- Bugzilla 18905: [Reg 2.079] C++ classes can no longer be used with -betterC
- Bugzilla 18936: Internal error: dmd/backend/cgxmm.c 684
- Bugzilla 19024: [REG 2.081-beta] AssertError@dmd/dsymbolsem.d(4317): Assertion failure
DMD Compiler bugs
- Bugzilla 5153: Struct pointer to struct variable assign error message
- Bugzilla 7443: Better diagnostic on wrongly written static constructor
- Bugzilla 11742: cannot inizialize void initialized static variable in static constructor.
- Bugzilla 12764: Disabled struct default construction circumvented when field is written to
- Bugzilla 12807: UFCS checks "alias this" attributes even when not called
- Bugzilla 13435: Strange error if struct is a class member and opAssign applied
- Bugzilla 13741: std.traits.moduleName & packageName do not work with functions that have parameters
- Bugzilla 14178: C++ linux name mangling does not handle standard abbreviations for const types
- Bugzilla 14739: Immutable alias to template triggers dmd assert
- Bugzilla 15068: wrong error message on attempting to use type as template
- Bugzilla 15388: extern(C++) - typeof(null) should mangle as nullptr_t
- Bugzilla 15475: Ddoc code sample with unbalanced paren comes out as macro
- Bugzilla 15574: wrong order of linker arguments
- Bugzilla 15755: DMD segfault upon alias on alias on __trait(getAttributes, ...)
- Bugzilla 15869: RVO can overwrite argument
- Bugzilla 16088: Parse error for import expression in statement
- Bugzilla 16206: traits getOverloads fails when one of the overload is a templatized function
- Bugzilla 17373: traits getOverloads + multiple interface inheritance only see one of the interfaces' overloads
- Bugzilla 18228: this(this a){} doesn't generate postblit ctor; this(this){} does
- Bugzilla 18236: Invalid line reported on error casting enum
- Bugzilla 18266: ICE: should allow reusing identifier in declarations in disjoint scopes in a function
- Bugzilla 18365: header file generation doesn't include the return attribute
- Bugzilla 18584: Undefined identifier when not specifying 'this'
- Bugzilla 18730: dmd miscompiles core.bitop.bt with -O
- Bugzilla 18746: function returning empty struct isn't called if used in equality expression
- Bugzilla 18775: DMD falsely reports deprecation for deprecated implicit casts that were not used in UFCS
- Bugzilla 18803: just "static if" in nested import crashes dmd
- Bugzilla 18828: [-betterC] helpless error in object.d
- Bugzilla 18858: switch 'skips declaration' test only checks last declaration
- Bugzilla 18868: Separate compilation generates two static this functions, runs it twice
- Bugzilla 18888: extern(C++) template arg/alias arg mangling issue
- Bugzilla 18890: extern(C++) mangles all destructors the same
- Bugzilla 18891: extern(C++) destructor prototype should just link; not generate field/aggregate dtor
- Bugzilla 18892: Wrong type in error message for static members and alias this
- Bugzilla 18916: ICE using Typedef and __LINE__
- Bugzilla 18922: dmd doesn't do substitutions for C++ namespaces in different module/file
- Bugzilla 18928: extern(C++) bad codegen, wrong calling convention
- Bugzilla 18951: package static method masked by public static method in class
- Bugzilla 18953: Win32: extern(C++) struct destructor not called correctly through runtime
- Bugzilla 18957: extern(C++) doesn't mangle 'std' correctly on posix systems
- Bugzilla 18966: extern(C++) constructor should match C++ semantics assigning vtable
- Bugzilla 18970: DMD segfault due to opDispatch
- Bugzilla 18976: Inconsistency in overload merging with aliases
- Bugzilla 18984: Debugging stack structs which are returned causes incorrect debuginfo.
DMD Compiler enhancements
- Bugzilla 14086: Invalid extern C++ name for constructor / destructor
- Bugzilla 15589: extern(C++) virtual destructors are not put in vtbl[]
- Bugzilla 15691: Improve error message for struct member initializer
- Bugzilla 18859: Silence class allocator/deallocator deprecation warning if they are marked "deprecated"
- Bugzilla 18963: Relax restrictions on 'return' parameters when parameter is not a pointer
Phobos regressions
- Bugzilla 18937: [REG 2.080.0] std.experimental.allocator: compiling make needs an unreasonable amount of memory for structs that contain static arrays
- Bugzilla 18993: toLower is broken for UTF chars
Phobos bugs
- Bugzilla 12086: std.algorithm.remove + range of indices produces wrong results
- Bugzilla 17084: Can't sort array of structs with alias this: swap can't call non-@nogc function doesPointTo
- Bugzilla 17806: processAllocator getter will override set value if it was set before getter was called at least once
- Bugzilla 18415: Typedef ignores @disabled default constructor
- Bugzilla 18470: std.algorithm.splitter has frame access problems for custom preds
- Bugzilla 18525: Constraint on std.algorithm.mutation.remove fails with char[]
- Bugzilla 18760: theAllocator should hold a reference to the allocator that it uses
- Bugzilla 18847: std.allocator: Region uses .parent before it can be set
- Bugzilla 18934: std.concurrency receive throws assertion failure if message is a struct containing const data
- Bugzilla 18940: [std.net.curl]Can't run examples on page. cannot implicitly convert expression ... char[] to string
- Bugzilla 18952: std.experimental.checkedint.Saturate prints integral promotion deprecation message
- Bugzilla 19020: findSkip, findSplit and findSplitBefore return wrong results
- Bugzilla 19023: findSplitBefore and findSplitAfter give wrong bool result
Phobos enhancements
- Bugzilla 18178: std.path should be usable in @safe
- Bugzilla 18593: std.datetime.stopwatch.benchmark shouldn't optimize away its functions
- Bugzilla 18766: std.typecons.Tuple.toHash could be improved
- Bugzilla 18813: fromStringz should work with char, wchar and dchar
- Bugzilla 18837: MMFile should have opDollar
- Bugzilla 18948: std.uni.toLower and std.uni.toUpper should work with random access ranges
Druntime regressions
- Bugzilla 18996: Inserting a type containing indirections into an std.container Array causes SIGILL(4). Illegal Instruction.
- Bugzilla 19005: [REG2.081-b1] object.hashOf no longer works for std.datetime.date.Date
Druntime bugs
- Bugzilla 14536: Calling destroy() on a on an extern(C++) class causes a segfault
- Bugzilla 18932: core.internal.hash.hashOf(val, seed) ignores seed when val is a raw pointer
- Bugzilla 18989: On OSX32, core.stdc.time.clock() should resolve to clock$UNIX2003()
- Bugzilla 19008: core.internal.convert.toUbyte doesn't work on enums
Druntime enhancements
- Bugzilla 18768: object.getArrayHash with custom toHash shouldn't just sum hashes of array elements
- Bugzilla 18920: core.internal.hash of array of scalars should be @safe
- Bugzilla 18924: Use addition rather than XOR for order-independent hash combination
- Bugzilla 18925: core.internal.hash auto-hash for structs of scalar fields should be @safe
- Bugzilla 18943: core.internal.hash remove outdated special case for DMD unaligned reads
dlang.org bugs
- Bugzilla 18752: std.file.read runnable example fails
- Bugzilla 18761: Page for assumeUnique documentation displays incorrectly
dlang.org enhancements
- Bugzilla 14099: Promote DPaste (dpaste.dzfl.pl) to run.dlang.org
- Bugzilla 18869: Add Jumia Food to organizations using D
- Bugzilla 18874: Add thatneedle.com to organizations using D
- Bugzilla 18959: [Change Log: 2.079.0] substitute was added in std.algorithm.iteration but the changelog points to std.algorithm.searching
Contributors to this release (51)
A huge thanks goes to all the awesome people who made this release possible.
- aG0aep6G
- Alexandru Jercaianu
- Andrei Alexandrescu
- Basile Burg
- Bastiaan Veelo
- BBasile
- carblue
- David Bennett
- David Gileadi
- Diederik de Groot
- Dmitry Olshansky
- Eduard Staniloiu
- Giles Bathgate
- Iain Buclaw
- Jack Stouffer
- Jacob Carlborg
- jercaianu
- Joakim Noah
- Johan Engelen
- John Colvin
- Jonathan Marler
- kinke
- Leandro Lucarella
- leitimmel
- Manu Evans
- Martin Nowak
- Mathias Lang
- Mathis Beer
- Mike Franklin
- Mike Parker
- Nathan Sashihara
- Nicholas Lindsay Wilson
- Nick Treleaven
- Quirin F. Schroll
- Radosław Rusiniak
- Radu Racariu
- Rainer Schuetze
- Razvan Nitu
- Remi Thebault
- Roman Chistokhodov
- Sebastian Wilzbach
- Simen Kjærås
- Steven Schveighoffer
- Tero Hänninen
- thaven
- Thibaut CHARLES
- Timon Gehr
- Timoses
- Tomáš Chaloupka
- Vladimir Panteleev
- Walter Bright