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

previous version: 2.101.2 – next version: 2.102.1

Download D 2.102.0
released Feb 01, 2023

2.102.0 comes with 15 major changes and 75 fixed Bugzilla issues. A huge thanks goes to the 40 contributors who made 2.102.0 possible.

List of all bug fixes and enhancements in D 2.102.0.

Compiler changes

  1. A missed case of conflicting extern (D) @system function definitions has been deprecated

    Having multiple definitions of functions within a module had been turned into an error in DMD 2.095.0.

    However, the compiler would not issue an error when two implementations differed by an explicit and inferred @system attribute, although they have the same mangling.

    void foo() {}
    void foo() @system {} // no error
    

    This bug has been fixed, and DMD will now issue a deprecation if there are such conflicting @system function implementations. Starting from DMD 2.112, it will produce a multiple definition error just like other kinds of conflicting functions within a module.

  2. Deprecate the ability to call __traits(getAttributes) on overload sets

    Up until this release, __traits(getAttributes) could be called both on individual functions and on overload sets. However, in the latter case, the compiler simply collected the user defined attributes for the first lexically defined function. This behavior is error prone. Consider:

    module test;
    
    @("gigi")
    void fun() {}
    @("mimi")
    void fun(int) {}
    
    void main()
    {
        static foreach(attr; __traits(getAttributes, fun))
            pragma(msg, attr);
    

    The above code will print "gigi" although there is no indication on what overload is actually queried. The first one is always picked.

    Starting with this release, this sort of usage of __traits(getAttributes) is deprecated. If a specific overload needs to be handled, __traits(getOverloads) may be used in conjunction with __traits(getAttributes) for proper behavior:

    module test;
    
    @("gigi")
    void fun() {}
    @("mimi")
    void fun(int) {}
    
    void main()
    {
        static foreach (t; __traits(getOverloads, test, "fun"))
            static foreach(attr; __traits(getAttributes, t))
                pragma(msg, attr);
    

    The above code prints:

    gigi
    mimi
    
  3. Deprecate non-empty for statement Increment clause with no effect

    The last clause of a for statement should not produce a value without also having some meaningful side-effect. This is now detected with a deprecation message. The following for statements each trigger the deprecation:

    // evaluating `j` has no side-effects
    int j;
    for (;; j) {...}
    
    // unnecessary dereference
    for (ubyte* sp;; *sp++) {...}
    
    // first clause is a block statement
    // last clause is a function literal, not a block statement
    for({j = 2; int d = 3;} j + d < 7; {j++; d++;}) {...}
    

    Note: Calling a function returning void is not deprecated even if the function does nothing. This is for generic code.

  4. Array literals assigned to scope array variables can now be allocated on the stack

    Formerly, they were always allocated with the Garbage Collector, making it unavailable in @nogc or -betterC code. This led to frequent use of the following workaround:

    void main() @nogc
    {
        int[3] buffer = [10, 20, 30];
        int[] arr = buffer[];
    }
    

    This can now be written in a single line:

    void main() @nogc
    {
        scope int[] arr = [10, 20, 30];
    }
    

    With the following limitations:

    • The variable must be explicitly annotated scope, not just inferred scope
    • The -preview=dip1000 must be passed, to prevent introducing memory corruption in legacy code.
    Note that in @system and @trusted code, the compiler doesn't verify that your scope variable doesn't escape.
    • The array literal must be initializing the variable. Subsequent array literals assignments still use the GC.
    • The array elements may not have a destructor

    Some of these limitations might get lifted in the future.

  5. static assert now supports multiple message arguments

    When the condition evaluates to false, any subsequent expressions will each be converted to string and then concatenated. The resulting string will be printed out along with the error diagnostic.

    enum e = 3;
    static assert(false, "a = ", e);
    

    Will print:

    file.d(2): Error: static assert:  a = 3
    

  6. -preview=systemVariables has been added

    Since DIP 1035 - System Variables has been accepted, variables marked @system may no longer be accessed from @safe code. To avoid code breakage, the compiler will start with emitting deprecation warnings. The preview switch will turn these into errors, and it will be enabled by default in a future release.

    @system int* p;
    
    struct S
    {
        @system int i;
    }
    
    void main() @safe
    {
        int x = *p; // error with `-preview=systemVariables`, deprecation otherwise
    
        S s;
        s.i = 0; // ditto
    }
    

    Note that currently this is limited to variables explicitly marked @system, inference of @system based on a variable's initializer is yet to be implemented.

Runtime changes

  1. The default Throwable.TraceInfo generation now is @nogc.

    The way this works:

    1. The runtime now has 2 trace-related functions, one for allocating a traceinfo, and one for deallocating the traceinfo. Both are set via the same Runtime.traceHandler function. The second parameter that sets the deallocation function is optional (so existing code will not be affected).
    2. When a Throwable is thrown, if the trace info is not yet set, the runtime uses the designated function to allocate a trace info. If the deallocation function is non-null, the function pointer is copied into the Throwable, into the new member infoDeallocator.
    3. When the Throwable is destroyed, if the infoDeallocator member is set, it is called on the info member.

    The default allocator and deallocator now uses C malloc and free to allocate and deallocate the TraceInfo. Almost everything was already nogc, except for the allocation of the TraceInfo object itself.

    The benefits:

    1. Stack traces can now be generated when run inside the GC collection routine.
    2. InvalidMemoryOperationError now has a stack trace.
    3. Little known is that even inside @nogc functions, throwing a Throwable actually was using the GC, that is no longer the case (by default).
    4. Certain GC hangs have been fixed (see bug fixes listed below).

    One possible drawback is that the TraceInfo is deallocated upon Throwable being finalized, leading to a potential dangling pointer situation. If you do copy the info out of the Throwable, makes sure to not keep it beyond the lifetime of the Throwable, or make sure to set the infoDeallocator member to null.

Library changes

  1. Single- and double-precision implementations for log function families

    New float and double overloads of std.math.exponential.log, std.math.exponential.log10, std.math.exponential.log1p, std.math.exponential.log2, and std.math.exponential.logb have been added to Phobos with proper 'software' implementations in the corresponding precision. Furthermore, std.math.exponential.logb is now pure.

    While this may result in a slowdown in some cases for DMD, the overall speed-up factor for GDC and LDC is over 3x, for both double and float.

    This also implies less precise results, especially in single-precision, so if your code depended on more accurate results via 80-bit intermediate precision, you'll have to cast the argument(s) explicitly now.

  2. The Unicode property "C" aka "Other" has had the wrong properties associated with it.

    If you use unicode.c or unicode.Other (case insensitive) from std.uni, you should mitigate or fix your codebase.

    This change makes it match the Unicode Techical Report #44. Unfortunately if you are already using it with its previous wrong values, this will break your code, below is a function which reflects the original values that you can use to mitigate against any breakage.

    @property auto loadPropertyOriginal(string name)() pure
    {
        import std.uni : unicode;
    
        static if (name == "C" || name == "c" || name == "other" || name == "Other")
        {
            auto target = unicode.Co;
            target |= unicode.Lo;
            target |= unicode.No;
            target |= unicode.So;
            target |= unicode.Po;
            return target;
        }
        else
            return unicode.opDispatch!name;
    }
    
  3. Unicode table generator is now in Phobos, tables are updated to version 15.

    It is likely that this change will result in breakage in code and program usage. This is due to a number of factors, the tables being updated so significantly and the table generator not having all its changes commited throughout the years.

  4. std.typecons.Unique now calls destroy on struct types

    When Unique goes out of scope, any destructor will now be called. Previously the destructor was not called then.

    static int i;
    
    struct S
    {
        ~this()
        {
            i++;
        }
    }
    {
        Unique!S u = new S;
        // S.~this now called here
    }
    assert(i == 1);
    

    Note: Above, the struct destructor will also be called by the GC just before the memory for new S is reclaimed. Take care that any struct destructor used will handle being called again on the struct .init value.

Installer changes

  1. Update the bundled VisualD package

    The VisualD package version that the installer downloads hasn't been updated in years. This has been remedied by a version bump to 1.3.1, the latest release of VisualD.

  2. Prefer 64 bit over 32 bit DMD on Windows 64 bit.

    The NSIS installer for Windows has the option "Add to PATH". Previously, only the 32 bit version of DMD was added to the PATH environment variable. Now, on Windows 64 bit, the 64 bit version of DMD will be selected from PATH.

Dub changes

  1. Binary output will now be in a central cache

    Up until now, dub would output build artifact in the package directory.

    This allowed reuse of build artifact for dependencies, but also created issues with large amount of build artifacts in the packages folder, preventing the use of read-only location to store packages, and making garbage collection of build artifacts unreliable.

    Starting from this version, build artifacts will be output by default to $HOME/.dub/cache/build/$BASE_PACKAGE_NAME/$PACKAGE_VERSION/[+$SUB_PACKAGE_NAME] on Linux, and %APPDATA%/cache/build/$BASE_PACKAGE_NAME/$PACKAGE_VERSION/[+$SUB_PACKAGE_NAME] on Windows.

  2. DUB API breaking change: Package.metadataCache setter and getter have been removed

    Those two functions were used to provide access to the metadata cache file to the generator. They were never intended for public consumption, and the JSON file format was not stable.

    Due to the introduction of the build cache, they needed to be removed, as there was no way to provide a sensible transition path, and they should be unused. If you have a use case for it, please open an issue in dub repository.


List of all bug fixes and enhancements in D 2.102.0:

DMD Compiler regression fixes

  1. Bugzilla 19268: BetterC turns off .dup for CTFE
  2. Bugzilla 20520: Runtime segfault when taking typeid of a class instanciated within an enum
  3. Bugzilla 21301: Wrong values being passed in long parameter list
  4. Bugzilla 23307: [REG][CODEGEN][SIMD] wrong codegen with inlined local functions + SIMD
  5. Bugzilla 23539: [REG master] Scope C++ definition out of sync with D
  6. Bugzilla 23548: [REG 2.098] C sources files have precedent over D modules in imports
  7. Bugzilla 23569: [REG 2.081][ICE] Segmentation fault in in AggregateDeclaration::getType() (this=0x0) at src/dmd/aggregate.d:594
  8. Bugzilla 23587: cast(void) doesn't work for noreturn
  9. Bugzilla 23591: [REG 2.101] Invalid casts accepted by the compiler if from type is noreturn
  10. Bugzilla 23607: invalid code leading to an ICE due to an error message that's not emitted anymore
  11. Bugzilla 23626: [REG2.096] Template deduction with auto const ref Args... and delegate

DMD Compiler bug fixes

  1. Bugzilla 13060: @nogc reading an associative array
  2. Bugzilla 15414: __traits(getAttributes) should error if the function has multiple overloads
  3. Bugzilla 15712: extern(C) attribute inside extern(C) unittest is incorrectly ignored
  4. Bugzilla 18026: Stack overflow in ddmd/dtemplate.d:6241, TemplateInstance::needsCodegen()
  5. Bugzilla 19623: HERE string identifier cannot start with Unicode letter
  6. Bugzilla 19649: Misleading error message for duplicate constraints
  7. Bugzilla 21062: Confusing error when using a keyword as an identifier for a declaration
  8. Bugzilla 21506: misalignment of _argptr for variadic functions
  9. Bugzilla 21613: DMD crash: copy ctor + templated rvalue ctor
  10. Bugzilla 22759: ImportC: cannot modify const expression from dereferencing const pointer declared within function.
  11. Bugzilla 23122: enum member UDAs semantics are not checked properly
  12. Bugzilla 23218: ICE: src/dmd/backend/cgxmm.d:1373: Assertion `0' failed.
  13. Bugzilla 23412: void init member detection does not account for static arrays
  14. Bugzilla 23418: double argument is passed on stack, but assumed to be in XMM0 register
  15. Bugzilla 23447: wrong expression in error message when template instance doesn't match any overload
  16. Bugzilla 23462: dmd: src/dmd/backend/cod2.d:2158: Assertion cast(int)tysize((*e).Ety) <= REGSIZE() failed
  17. Bugzilla 23463: Don't count skipped function overloads when limiting overloads shown
  18. Bugzilla 23465: Invalid token error points to wrong line
  19. Bugzilla 23470: Backticks in diagnostic are confusing with wrong number of arguments passed
  20. Bugzilla 23491: Nonsensical deprecation message when using delegate
  21. Bugzilla 23531: [DIP1000] scope variable can be assigned as AA key
  22. Bugzilla 23534: __traits(isZeroInit) is true for enums with explicit values
  23. Bugzilla 23536: crt_constructors and crt_destructors should not be non-static member functions
  24. Bugzilla 23568: Error: cannot implicitly convert expression 'a < b' of type 'float4' to 'int4'
  25. Bugzilla 23578: Types are not matched to alias parameters in "is" expression
  26. Bugzilla 23586: DMD forgets a variable was just declared.
  27. Bugzilla 23593: core.thread: suspendAll doesn't wait for all if current thread has detached itself
  28. Bugzilla 23614: ImportC: __int128 not supported
  29. Bugzilla 23618: Right Shift equals expressions on unsigned shorts should be unsigned right shift
  30. Bugzilla 23620: 'alias this' is not respected in static array length position

DMD Compiler enhancements

  1. Bugzilla 9848: Better diagnostic when type declaration was not expected
  2. Bugzilla 15368: Improve error message for "auto" keyword inside "foreach"
  3. Bugzilla 21338: Confusing error message for template overload resolution failure
  4. Bugzilla 22306: scope array variable should be stack allocated
  5. Bugzilla 23410: ImportC: binary constants not allowed
  6. Bugzilla 23424: improve error when template instantiation doesn't match any overload
  7. Bugzilla 23458: No template candidates listed when OverDeclaration or OverloadSet don't match
  8. Bugzilla 23466: -verrors=context should not repeat same context for supplemental messages
  9. Bugzilla 23480: non-empty ForStatement Increment clause should require a side effect
  10. Bugzilla 23552: Function x does not override any function, but it actually does
  11. Bugzilla 23566: ImportC: __PRETTY_FUNCTION__ is not defined

Phobos bug fixes

  1. Bugzilla 23319: std.range.Generator does not work with non-mutable elements
  2. Bugzilla 23488: std.format.sformat mishandles char ranges
  3. Bugzilla 23507: Socket.blocking property incorrect on new Socket on Windows
  4. Bugzilla 23540: std.uni loadProperty aliases for C are incorrect
  5. Bugzilla 23561: std.typecons.Unique!struct does not destroy struct instance
  6. Bugzilla 23640: Nullable range iteration doesn't work with immutable values

Phobos enhancements

  1. Bugzilla 19737: [std.experimental.allocator] link table in docs has missing symbols
  2. Bugzilla 23453: Generic iota should be a forward range

Druntime regression fixes

  1. Bugzilla 22616: Infinity loop instead of InvalidMemoryOperationError during GC routine
  2. Bugzilla 23562: [REG master] Segmentation fault in core.demangle

Druntime bug fixes

  1. Bugzilla 16641: Infinite loop on InvalidMemoryOperationError in __dmd_personality_v0
  2. Bugzilla 19467: Support EV_SET on OSX
  3. Bugzilla 23572: OpenBSD: Add OpenBSD to the RTLD_DEFAULT list

Druntime enhancements

  1. Bugzilla 20650: Cryptic error message when GC called in finalizer
  2. Bugzilla 23332: core.sync.condition notify methods should be @nogc

dlang.org bug fixes

  1. Bugzilla 23382: Non-template requirement for copy constructors is undocumented
  2. Bugzilla 23436: Spec falsely states mutable references in struct .init are forbidden
  3. Bugzilla 23541: [ImportC] dlang.org contains incorrect links

dlang.org enhancements

  1. Bugzilla 23426: Example Run button shows wrong line numbers for errors
  2. Bugzilla 23432: document when array capacity is zero and capacity performance
  3. Bugzilla 23511: Incrementing a not supported type in enum
  4. Bugzilla 23553: opCmp spec is incomplete

Installer bug fixes

  1. Bugzilla 23623: On 64 bit Windows the path should point to 64 bit dmd.

Contributors to this release (40)

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

previous version: 2.101.2 – next version: 2.102.1