released May 01, 2018
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 theDeprecated Features for more information.
Many alternatives for class allocators/deallcators exist. Among them is the genericstd.experimental.allocator.make andstd.experimental.allocator.dispose from the allocator package. For other alternatives, seethe recent article about memory allocation on the DBlog andthe D Wiki memory management article.
Users have leveraged allocators in order to disable GC allocation, as illustrated in the following example:
class C{ @disablenew(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 thesize_t argument. That is, starting with this release, the following syntax is also permitted:
class C{ @disablenew();}void main(){auto c =new C();// Error: allocator `new` is not callable because it is annotated with `@disable`}
Inside a constructor scope, assigning to aggregate declaration (class/struct)members is done by considering the first assignment as initialization andsubsequent assignments as modifications of the initially constructed object.Forconst/immutable fields the initialization is accepted in the constructor,but subsequent modifications are not. Example:
struct A{int a;immutableint b;this(int a,int b) {this.a = a;this.b = b;this.a = 7;// OK, a is mutablethis.b = 9;// Error: immutable field b initialized multiple times }}
However,Bugzilla 18719 shows that this rule does not apply when insidea constructor scope there is a call to a different constructor:
struct A{ immmutableint 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 doubleinitialization of theimmutable fielda. After this patch,this.a = 5 will issuea deprecation warning stating thata is initialized multiple times.
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 eachfield is initialized exactly once. To get code like the aboveto pass the compiler, replace it with an if-then sequence.
The pow operator^^ can now be used by CTFE.
Adds these std.math functions to those that can be used by CTFE:
roundfloorceiltruncloglog2log10powexpm1exp2fminfmaxcopysignfma
Determines if a function's return value is placed on the stack,or is returned via registers.For more details, seeisReturnOnStack.
Previously to call an Objective-C class method it was necessary to make explicitcalls to the Objective-C runtime. The following code is an example of the oldway to call a class method:
extern (C) Class objc_lookUpClass(inchar* 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 thestatic attribute in the method declaration.
Before this patch, if a postblit was declaredconst/immutable/sharedthe compiler would have accepted the declaration but there would havebeen no way of calling the postblit succesfully, except for const dueto the implicit conversion mutable -> const. Even though calling aconst posblit is possible, there is no way to modify the fields of thenewly copied struct:
struct S{int nthis(this)const { ++n;// Error: cannot modify this.n in const method }}void main(){ S a;auto a2 = a;}
With this release, if a postblit containsconst/immutable/shared inits signature, a deprecation message will be emitted.
Read-modify-write operations are not allowed forshared variables:
sharedint i;i++;// Error: read-modify-write operations are not allowed for shared variables
Usecore.atomic.atomicOp instead:
import core.atomic : atomicOp;sharedint i;atomicOp!"+="(i, 1);
Usage of a variable which is declared in anotherswitch 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 -321532879break; }default:break;}
If this behavior is wanted, it can explicitly requested by usingvoid initialization:
int i = 2;switch (i){case 1: {int j =void;case 2: j = 2; j.writeln;break; }default:break;}
std.typecons.BitFlags was extended so that enum members can be set and tested directly on theBitFlags instead of having to& with the underlying enum.
enum Features{ fast = 1 << 0, size = 1 << 1,}void run(BitFlags!Features features){// getif (features.fast && !features.size) {}// new new newif ((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 unsafeBitFlags where the property get access tests for an exactmatch of all bits of the unsafeBitFlags combination.Analogously, the property set access clears or sets all bits of the unsafeBitFlags combination.
enum Features{ fast = 1 << 0, size = 1 << 1, combined = fast | size,}void run(BitFlags!(Features, Yes.unsafe) features){// getif (features.combined) {}// new new newif ((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 is a rounding function only available when using theDigital Mars C Runtime on Windows. As this function is not cross-platform, ithas been deprecated, and will be removed on version 2.089. Please usestd.math.round instead.
The newstd.experimental.allocator.building_blocks.bitmapped_block.SharedBitmappedBlock and its single-threaded version can now be instantiated withYes.multiblock orNo.multiblock.If instantiated withYes.multiblock (the default behavior), each allocation can return an arbitrary number of blocks.WithNo.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.multiblockauto a = BitmappedBlock!(blockSize, 8, Mallocator, Yes.multiblock)(numBlocks * blockSize);// Instantiated with Yes.multiblock, can allocate more than one block at a timevoid[] buf = a.allocate(2 * blockSize);assert(buf.length == 2 * blockSize);assert(a.deallocate(buf));
// Instantate the 'BitmappedBlock' with No.multiblockauto a = BitmappedBlock!(blockSize, 8, Mallocator, No.multiblock)(1024 * blockSize);// Since instantiated with No.multiblock, can only allocate at most the block sizevoid[] buf = a.allocate(blockSize + 1);assert(bufisnull);
For shared the same rules apply, we only need to replaceBitmappedBlock withSharedBitmappedBlock.
std.experimental.allocator.building_blocks.aligned_block_list.AlignedBlockList representsa 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. TheParentAllocator must implementalignedAllocate.
std.experimental.allocator.building_blocks.aligned_block_list.SharedAlignedBlockList has thesame semantics as its single threaded version, however the internal allocators must be in addition markedas shared.
With 2.079std.exception.enforce became a complete super set ofstd.exception.enforceEx
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"));
std.format.formatValue now correctly groups digits in the output stringby inserting a group separator character (,) every n characters specifiedby theSeparatorgrammar rule in cases with zero decimal precision specified in the format stringfor floating point numbers.
No group separators at all are inserted for floating point numbers when formattedwith 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.reverseArgs is a full super set ofstd.functional.binaryReverseArgs.
Correct action: replacebinaryReverseArgs withreverseArgs.
apply is an operation forstd.typecons.Nullable values that "unpacks" theNullable, performs someoperation (that is passed as a template parameter), then packs the result into anotherNullable if necessary.When the initialNullable isnull, the resultingNullable is alsonull and the function is notcalled.
Nullable!int n;alias square = i => i * i;n = n.apply!square;// does nothing if isNullassert(n.isNull);n = 2;assert(n.apply!square.get == 4);
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 = --evalhello.txt: import std.file; write("$@","hello world\n");
A huge thanks goes to all the awesome people who made this release possible.