Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

Change Log: 2.081.0

previous version: 2.080.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



List of all upcoming bug fixes and enhancements in D 2.081.0.

Compiler changes

  1. 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`
    }
    
  2. 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()).

  3. 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.

  4. Deprecate the usage of this as a parameter type

    Before this patch, the keyword this could be used as a function parameter type. This is incosistent with the meaning of this (the current instance of an aggregate declaration). In addition, accepting this as a function parameter type leads to inconsistencies when defining a struct postblit:

    struct A
    {
        this(this a) {}
    }
    

    In the above example this(this a) is not considered a postblit, but a constructor which has a parameter of type A named a. This is incosistent with the D optional parameter system where a function int fun(int a) is equivalent to int fun(int) if the parameter is unused.

    After this patch, the compiler will issue a deprecation warning whenever it encounters this as a parameter type:

    struct A
    {
        this(this a) {} // Deprecation: `this` cannot be used as a parameter type.
                        //Use `typeof(this)` instead
    
        this(int a, this b) {} // ditto
    }
    
  5. 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.

  6. 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

  7. 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.

  8. 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.

  9. 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.

  10. 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.

  11. 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 atomic.atomicOp.core instead:

    import core.atomic : atomicOp;
    shared int i;
    atomicOp!"+="(i, 1);
    
  12. 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;
    }
    

List of all bug fixes and enhancements in D 2.081.0:

DMD Compiler bugs

  1. Bugzilla 7443: Better diagnostic on wrongly written static constructor
  2. Bugzilla 11742: cannot inizialize void initialized static variable in static constructor.
  3. Bugzilla 12807: UFCS checks "alias this" attributes even when not called
  4. Bugzilla 13435: Strange error if struct is a class member and opAssign applied
  5. Bugzilla 15574: wrong order of linker arguments
  6. Bugzilla 17373: traits getOverloads + multiple interface inheritance only see one of the interfaces' overloads
  7. Bugzilla 18228: this(this a){} doesn't generate postblit ctor; this(this){} does
  8. Bugzilla 18584: Undefined identifier when not specifying 'this'
  9. Bugzilla 18730: dmd miscompiles core.bitop.bt with -O
  10. Bugzilla 18746: function returning empty struct isn't called if used in equality expression
  11. Bugzilla 18775: DMD falsely reports deprecation for deprecated implicit casts that were not used in UFCS
  12. Bugzilla 18803: just "static if" in nested import crashes dmd

Phobos bugs

  1. Bugzilla 17084: Can't sort array of structs with alias this: swap can't call non-@nogc function doesPointTo
  2. Bugzilla 17806: processAllocator getter will override set value if it was set before getter was called at least once
  3. Bugzilla 18525: Constraint on std.algorithm.mutation.remove fails with char[]
  4. Bugzilla 18760: theAllocator should hold a reference to the allocator that it uses

Contributors to this release (28)

A huge thanks goes to all the awesome people who made this release possible.

previous version: 2.080.0