Change Log: 2.080.0
Download D 2.080.0
released May 01, 2018
Compiler changes
- Class allocators and deallocators have been deprecated
- Deprecate double initialization of immutable fields inside constructor
- Issue 18736 - constructor calls allowed after case labels
- fix Issue 5227 - X ^^ FP at compile-time
- add __traits(isReturnOnStack, func)
- Support for calling Objective-C class (static) methods has been added.
- Deprecate the use of a const/immutable/shared postblit
- The deprecation for read-modify-write operations on shared variables has ended
- The deprecation for switch cases which skip the declaration of a variable has ended
Library changes
- std.typecons.BitFlags now supports opDispatch-based property access
- std.math.rndtonl has been deprecated
- Added the SharedBitmappedBlock, as the thread-safe version of the regular BitmappedBlock.
- Implemented a new allocator, AlignedBlockList and its thread-safe version SharedAlignedBlockList
- std.exception.enforceEx was deprecated in favor of std.exception.enforce
- Fixed digits grouping for floating point number without decimal part
- std.functional.binaryReverseArgs was deprecated in favor of std.functional.reverseArgs
- apply was added to std.typecons.
Tools changes
List of all bug fixes and enhancements in D 2.080.0.
Compiler changes
- Class allocators and deallocators have been deprecated
Class allocators and deallocators have been planned for deprecation for years. Starting with this release the following code will emit deprecation messages.
class C { new(size_t size) // deprecation message { return malloc(size); } delete(void* obj) // deprecation message { free(obj); } }
See the Deprecated Features for more information.
Many alternatives for class allocators/deallcators exist. Among them is the generic std.experimental.allocator.make and std.experimental.allocator.dispose from the allocator package. For other alternatives, see the recent article about memory allocation on the DBlog and the D Wiki memory management article.
Users have leveraged allocators in order to disable GC allocation, as illustrated in the following example:
class C { @disable new(size_t size); } void main() { auto c = new C(); // Error: allocator `new` is not callable because it is annotated with `@disable` }
That idiom will remain, but has been enhanced with this release to no longer require the size_t argument. That is, starting with this release, the following syntax is also permitted:
class C { @disable new(); } void main() { auto c = new C(); // Error: allocator `new` is not callable because it is annotated with `@disable` }
- Deprecate double initialization of immutable fields inside constructor
Inside a constructor scope, assigning to aggregate declaration (class/struct) members is done by considering the first assignment as initialization and subsequent assignments as modifications of the initially constructed object. For const/immutable fields the initialization is accepted in the constructor, but subsequent modifications are not. Example:
struct A { int a; immutable int b; this(int a, int b) { this.a = a; this.b = b; this.a = 7; // OK, a is mutable this.b = 9; // Error: immutable field b initialized multiple times } }
However, Bugzilla 18719 shows that this rule does not apply when inside a constructor scope there is a call to a different constructor:
struct A { immmutable int a; this() { this(42); this.a = 5; // second initialization of immutable field } this(int a) { this.a = a; } }
The above code wrongfully compiled succesfully before this patch, accepting the double initialization of the immutable field a. After this patch, this.a = 5 will issue a deprecation warning stating that a is initialized multiple times.
- Issue 18736 - constructor calls allowed after case labels
Delegating constructor calls are not allowed after labels, but case labels and default labels should also count as labels.
class A { this(char c) { } this(int i) { switch (i) { case 1: break; default: break; } this('c'); // now gives an error } }
This is necessary so the compiler can guarantee that each field is initialized exactly once. To get code like the above to pass the compiler, replace it with an if-then sequence.
- fix Issue 5227 - X ^^ FP at compile-time
The pow operator ^^ can now be used by CTFE.
Adds these std.math functions to those that can be used by CTFE:
round floor ceil trunc log log2 log10 pow expm1 exp2 fmin fmax copysign fma
- add __traits(isReturnOnStack, func)
Determines if a function's return value is placed on the stack, or is returned via registers. For more details, see isReturnOnStack.
- Support for calling Objective-C class (static) methods has been added.
Previously to call an Objective-C class method it was necessary to make explicit calls to the Objective-C runtime. The following code is an example of the old way to call a class method:
extern (C) Class objc_lookUpClass(in char* name); extern (Objective-C) interface Class { NSObject alloc() @selector("alloc"); } extern (Objective-C) interface NSObject { NSObject init() @selector("init"); } void main() { auto cls = objc_lookUpClass("NSObject"); auto o = cls.alloc().init(); }
The above code can now be replaced with the following:
extern (Objective-C) interface NSObject { static NSObject alloc() @selector("alloc"); NSObject init() @selector("init"); } void main() { auto o = NSObject.alloc().init(); }
Note the use of the static attribute in the method declaration.
- Deprecate the use of a const/immutable/shared postblit
Before this patch, if a postblit was declared const/immutable/shared the compiler would have accepted the declaration but there would have been no way of calling the postblit succesfully, except for const due to the implicit conversion mutable -> const. Even though calling a const posblit is possible, there is no way to modify the fields of the newly copied struct:
struct S { int n this(this) const { ++n; // Error: cannot modify this.n in const method } } void main() { S a; auto a2 = a; }
With this release, if a postblit contains const/immutable/shared in its signature, a deprecation message will be emitted.
- The deprecation for read-modify-write operations on shared variables has ended
Read-modify-write operations are not allowed for shared variables:
shared int i; i++; // Error: read-modify-write operations are not allowed for shared variables
Use core.atomic.atomicOp instead:
import core.atomic : atomicOp; shared int i; atomicOp!"+="(i, 1);
- The deprecation for switch cases which skip the declaration of a variable has ended
Usage of a variable which is declared in another switch case now results in an error.
int i = 2; switch (i) { case 1: { int j; case 2: j++; j.writeln; // BUG: j is not initialized and e.g. prints -321532879 break; } default: break; }
If this behavior is wanted, it can explicitly requested by using void initialization:
int i = 2; switch (i) { case 1: { int j = void; case 2: j = 2; j.writeln; break; } default: break; }
Library changes
- std.typecons.BitFlags now supports opDispatch-based property access
std.typecons.BitFlags was extended so that enum members can be set and tested directly on the BitFlags instead of having to & with the underlying enum.
enum Features { fast = 1 << 0, size = 1 << 1, } void run(BitFlags!Features features) { // get if (features.fast && !features.size) {} // new new new if ((features & Features.fast) && !(features & Features.size)) {} // old old old // set features.fast = true; // new new new features.fast = false; // new new new features.fast |= Features.fast; // old old old features.fast &= ~Features.fast; // old old old }
This also works for unsafe BitFlags where the property get access tests for an exact match of all bits of the unsafe BitFlags combination. Analogously, the property set access clears or sets all bits of the unsafe BitFlags combination.
enum Features { fast = 1 << 0, size = 1 << 1, combined = fast | size, } void run(BitFlags!(Features, Yes.unsafe) features) { // get if (features.combined) {} // new new new if ((features & Features.combined) == BitFlags!(Features, Yes.unsafe)(Features.combined)) {} // old old old // set features.combined = true; // new new new features.combined = false; // new new new features.combined |= Features.combined; // old old old features.combined &= ~Features.combined; // old old old }
- std.math.rndtonl has been deprecated
std.math.rndtonl is a rounding function only available when using the Digital Mars C Runtime on Windows. As this function is not cross-platform, it has been deprecated, and will be removed on version 2.089. Please use std.math.round instead.
- Added the SharedBitmappedBlock, as the thread-safe version of the regular BitmappedBlock.
The new std.experimental.allocator.building_blocks.bitmapped_block.SharedBitmappedBlock and its single-threaded version can now be instantiated with Yes.multiblock or No.multiblock. If instantiated with Yes.multiblock (the default behavior), each allocation can return an arbitrary number of blocks. With No.multiblock however, any allocation request can't exceed the block size. This allows for greater performance on both single and multithreaded environments.
// The 'BitmappedBlock' is implicitly instantiated with Yes.multiblock auto a = BitmappedBlock!(blockSize, 8, Mallocator, Yes.multiblock)(numBlocks * blockSize); // Instantiated with Yes.multiblock, can allocate more than one block at a time void[] buf = a.allocate(2 * blockSize); assert(buf.length == 2 * blockSize); assert(a.deallocate(buf));
// Instantate the 'BitmappedBlock' with No.multiblock auto a = BitmappedBlock!(blockSize, 8, Mallocator, No.multiblock)(1024 * blockSize); // Since instantiated with No.multiblock, can only allocate at most the block size void[] buf = a.allocate(blockSize + 1); assert(buf is null);
For shared the same rules apply, we only need to replace BitmappedBlock with SharedBitmappedBlock.
- Implemented a new allocator, AlignedBlockList and its thread-safe version SharedAlignedBlockList
std.experimental.allocator.building_blocks.aligned_block_list.AlignedBlockList represents a list of allocators which allows for deallocations in constant time. Although allocations are in theory served in linear searching time, deallocate calls take Ο(1) time, by using aligned allocations. The ParentAllocator must implement alignedAllocate.
std.experimental.allocator.building_blocks.aligned_block_list.SharedAlignedBlockList has the same semantics as its single threaded version, however the internal allocators must be in addition marked as shared.
- std.exception.enforceEx was deprecated in favor of std.exception.enforce
With 2.079 std.exception.enforce became a complete super set of std.exception.enforceEx
Corrective action
Replace:
import std.exception; alias enf = enforceEx!Exception; assertNotThrown(enf(true)); assertThrown(enf(false, "blah"));
with:
import std.exception; alias enf = enforce!Exception; assertNotThrown(enf(true)); assertThrown(enf(false, "blah"));
- Fixed digits grouping for floating point number without decimal part
std.format.formatValue now correctly groups digits in the output string by inserting a group separator character (,) every n characters specified by the Separator grammar rule in cases with zero decimal precision specified in the format string for floating point numbers.
No group separators at all are inserted for floating point numbers when formatted with zero precision (i.e. no decimal digits) in Phobos before this fix, regardless of the respective decimal part of the formatted number.
import std.format; assert(format("%,3.2f", 1172.009) == "1,172.01"); assert(format("%,3.0f", 1172.009) == "1,172"); assert(format("%#,3.4f", 1303.2508) == "1,303.250,8"); assert(format("%#,3.0f", 1303.2508) == "1,303."); // original (buggy) behaviour before this fix //assert(format("%,3.0f", 1303.2508) == "1303"); //assert(format("%,3.0f", 1303.) == "1303"); // original (correct) behaviour before this fix //assert(format("%,3.1f", 1303.2508) == "1,303.3"); //assert(format("%,3.2f", 1303.) == "1,303.00"); //assert(format("%,3f", 1303.) == "1,303.000,000");
- std.functional.binaryReverseArgs was deprecated in favor of std.functional.reverseArgs
std.functional.reverseArgs is a full super set of std.functional.binaryReverseArgs.
Correct action: replace binaryReverseArgs with reverseArgs.
- apply was added to std.typecons.
apply is an operation for std.typecons.Nullable values that "unpacks" the Nullable, performs some operation (that is passed as a template parameter), then packs the result into another Nullable if necessary. When the initial Nullable is null, the resulting Nullable is also null and the function is not called.
Nullable!int n; alias square = i => i * i; n = n.apply!square; // does nothing if isNull assert(n.isNull); n = 2; assert(n.apply!square.get == 4);
Tools changes
- rdmd can now be used as a shell in makefiles
With gnu make(3.82 or higher), rdmd can now be used in makefiles. This is accomplished by setting the SHELL and .SHELLFLAGS to /usr/bin/rdmd and --eval respectively.
.ONESHELL: SHELL = /usr/bin/rdmd .SHELLFLAGS = --eval hello.txt: import std.file; write("$@","hello world\n");
List of all bug fixes and enhancements in D 2.080.0:
DMD Compiler regressions
- Bugzilla 16243: wrong C++ argument passing with empty struct when interfacing with Clang
- Bugzilla 18197: [REG2.073] Internal error: backend\cgcod.c 1659
- Bugzilla 18489: [REG 2.073]Internal error: dmd/backend/cgcod.c 1688
DMD Compiler bugs
- Bugzilla 5212: no escape analysis for typesafe variadic function arguments
- Bugzilla 5227: X ^^ FP at compile-time
- Bugzilla 9433: Deprecate delete
- Bugzilla 12486: Function returning struct isn't called if enum of its result is accessed
- Bugzilla 14997: __ctor present in error message
- Bugzilla 15653: IFTI fails for immutable parameter
- Bugzilla 15660: break immutable with pure function and mutable reference params
- Bugzilla 16107: [ICE] - Internal error: backend/cgcod.c 2297
- Bugzilla 16189: Optimizer bug, with simple test case
- Bugzilla 16555: Stack corruption when calling multi-parameter outer function from nested function
- Bugzilla 16578: bogus deprecation - switch skips declaration of variable
- Bugzilla 17284: Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions
- Bugzilla 17423: pointer assignment to this in member function is not accounted for
- Bugzilla 17874: Segmentation fault when constructing a struct with a static array of structs containing floats
- Bugzilla 17892: Scope analysis with -dip1000 fails for templated structs
- Bugzilla 17918: [Reg 2.072] ICE with unknown symbol in base class
- Bugzilla 17959: [DIP1000] Can store scope delegate in non-scope member
- Bugzilla 17991: ICE with imports without module
- Bugzilla 18000: [scope] auto-generated opAssign not scope aware
- Bugzilla 18034: SIMD optimization issues
- Bugzilla 18130: ICE on zero-length out array parameter
- Bugzilla 18199: Error with lambda in struct initializer
- Bugzilla 18242: DMD Segmentation fault.
- Bugzilla 18282: [Scope][DIP1000]Assignment of local variable to scope variable not recognized by compiler
- Bugzilla 18459: The static array ABI doesn't match the struct ABI
- Bugzilla 18461: codegen bug - OPbt expressions and assignments to ambiguous symbols
- Bugzilla 18474: Postblit not working in shared structs
- Bugzilla 18484: [dip1000] Subtype allows reference to escape with implicit casting
- Bugzilla 18504: Assert in synchronized crashes with SIGILL on exit
- Bugzilla 18505: delete deprecation message is misleading
- Bugzilla 18534: Wrong code for ?: operator when compiling with -O
- Bugzilla 18553: Inline assembler: CR2, CR3 control registers not available in 64-bit code
- Bugzilla 18554: tupleof ignoring private shouldn't be accepted in @safe code
- Bugzilla 18568: partially overlapping assignments have undefined behavior but are accepted in @safe code
- Bugzilla 18575: making delegate from member function can lead to unsafe code
- Bugzilla 18576: Compiler not doing RVO with auto returns
- Bugzilla 18597: more unsafe unaligned pointer errors
- Bugzilla 18607: using labelled continue in tuple foreach can break pure and @safe
- Bugzilla 18644: [dip1000] escape of outer local not detected
- Bugzilla 18661: auto ref and return attribute inference
- Bugzilla 18708: Flow analysis in constructors not done correctly for if, ||, &&
- Bugzilla 18719: Doubly-called constructor against member when using forwarding constructors
- Bugzilla 18736: constructor calls allowed after case labels
- Bugzilla 18737: An assert(0) should be a leaf in constructor flow analysis
- Bugzilla 18753: chunkBy compile error causes ICE
- Bugzilla 18762: DMD should use a unique path/filename for __stdin.o
DMD Compiler enhancements
- Bugzilla 15624: opApply with @safe and @system variants can't be used with foreach syntax
- Bugzilla 16037: assigning delegate to a scope variable shouldn't allocate closure
- Bugzilla 17784: [scope][DIP1000] Confusing error message for escaping local via new-expression
- Bugzilla 18417: Make const and immutable postblit constructors illegal
- Bugzilla 18460: Improve error message for missing 'new' for class instantiation
- Bugzilla 18503: Confusing error message for erroneous postblit
- Bugzilla 18551: Improve hint for "does not override any function
- Bugzilla 18574: Unclear error message when trying to inherit from multiple classes
- Bugzilla 18578: First enum value assigned 0 instead of EnumBaseType.init
- Bugzilla 18591: DMD should allow access to mixin template declarations
- Bugzilla 18694: pure functions using static/global structs with no fields should pass compilation
- Bugzilla 18767: __xtoHash memberwise hashing shouldn't just sum the member hashes
Phobos regressions
- Bugzilla 17961: std.uni does not compile with -unittest -dip1000
- Bugzilla 18800: [REG2.080.0-beta.1] Array.length setter segfaults for payloads with indirections
Phobos bugs
- Bugzilla 7879: format of class with not const toString()
- Bugzilla 13642: std.container.Array: change of length reallocates without notifying GC
- Bugzilla 15768: std.stdio.File does not support __gshared semantics of stdout/err/in
- Bugzilla 17862: std.random.XorshiftEngine.min is wrong when bits == 32
- Bugzilla 17982: Support for const(Class) in algorithm.searching.extremum
- Bugzilla 18133: BitArray constructors are poorly documented.
- Bugzilla 18134: BitArray >>= broken when length % (8 * size_t.sizeof) == 0
- Bugzilla 18452: std.zip has size limit of 2 GB
- Bugzilla 18524: std.range.Zip.moveBack instead performs moveFront
- Bugzilla 18579: No group separators for floating point number formatted with zero decimal digits
- Bugzilla 18615: Rebindable!A doesn't use class A's opEquals (returns a is b instead)
- Bugzilla 18634: std.container.rbtree does not work with delegate comparators
- Bugzilla 18663: std.random.isSeedable has false positives
- Bugzilla 18669: isNestedFunction does not check if parameter is a function
- Bugzilla 18689: std.format should always throw FormatException on bad specs/arguments
- Bugzilla 18704: std/datetime/stopwatch.d(452) assertion failure on auto-tester
- Bugzilla 18714: Phobos calls localtime, which is not threadsafe
Phobos enhancements
- Bugzilla 4591: Concat of std.typecons.Tuples
- Bugzilla 8341: topN(zip()) too?
- Bugzilla 10828: datetime toString functions should accept sink
- Bugzilla 13880: nothrow @nogc std.algorithm.reduce on fixed-size arrays
- Bugzilla 14637: Array operations should work on tuples
- Bugzilla 18158: std.file.getcwd should be usable in @safe
- Bugzilla 18166: std.array.replace should be usable in @safe for dstrings
- Bugzilla 18168: std.base64.encode for output ranges should be usable in @safe
- Bugzilla 18174: std.math.equalsDigit should be usable in @safe
- Bugzilla 18182: std.uri should be usable in @safe
- Bugzilla 18223: std.experimental.allocator uninitializedFillDefault could use memset
- Bugzilla 18438: hasStaticMember fails with a T* while hasMember passes
- Bugzilla 18501: randomShuffle and partialShuffle should return their input argument
- Bugzilla 18596: std.random.unpredictableSeed could use something better than MinstdRand0
- Bugzilla 18600: Regex performance enhancement for repeated matchFirst calls
- Bugzilla 18638: The main override of std.range.zip could infer @nogc and nothrow
Druntime regressions
- Bugzilla 18652: hashOf example doesn't compile
Druntime bugs
- Bugzilla 18482: wincrypt functions should be @nogc nothrow
- Bugzilla 18536: Bad stack traces when building with -m32mscoff
- Bugzilla 18537: Cannot pass absolute path to coverage options
- Bugzilla 18547: Win32: throwing exception in fiber crashes application
dlang.org bugs
- Bugzilla 18602: [Better C] docs
- Bugzilla 18603: Illegal instruction: 4 on Mac OS 10.7.5 Leopard
- Bugzilla 18702: FAQ item "What does D have that C++ doesn't?" comparison link (https://dlang.org/articles/comparison.html) returns 404
- Bugzilla 18709: DDOC_AUTO_PSYMBOL and friends are wrong
- Bugzilla 18747: [Structs, Unions]
Installer bugs
- Bugzilla 18649: curl on Ubuntu 18.04 depends on libcurl4, .deb installer depends on libcurl3
Contributors to this release (65)
A huge thanks goes to all the awesome people who made this release possible.
- Adam D. Ruppe
- aG0aep6G
- Alexandru Caciulescu
- Alexandru Jercaianu
- Ali Akhtarzada
- Andrei Alexandrescu
- Andrei-Cristian VASILE (87585)
- Basile Burg
- Brad Roberts
- byebye
- carblue
- cedretaber
- crimaniak
- David Nadlinger
- Denis Feklushkin
- Diederik de Groot
- Dmitry Olshansky
- drug007
- Eduard Staniloiu
- FeepingCreature
- Giles Bathgate
- Harry T. Vennik
- Iain Buclaw
- Jack Stouffer
- Jacob Carlborg
- Joakim Noah
- Johan Engelen
- John Belmonte
- Jonathan M Davis
- Jonathan Marler
- Joseph Rushton Wakeling
- Kai Nacke
- kinke
- LemonBoy
- Martin Kinkelin
- Martin Nowak
- Mathias Lang
- Mathis Beer
- MetaLang
- Mike Franklin
- Mike Parker
- n8sh
- Nathan Sashihara
- Nicholas Lindsay Wilson
- Nick Treleaven
- Oleg Nykytenko
- Per Nordlöw
- Radu Racariu
- Rainer Schuetze
- Razvan Nitu
- Roman Chistokhodov
- rracariu
- Ryan Frame
- Sebastian Wilzbach
- Simon Naarmann
- skl131313
- Steven Schveighoffer
- Superstar64
- Thomas Mader
- Timothee Cour
- Unknown
- viktor
- Vladimir Panteleev
- Walter Bright
- Ľudovít Lučenič