Change Log: 2.097.0
Download D 2.097.0
released Jun 03, 2021
Compiler changes
- Deprecation period for ambiguous ternary expressions has ended
- Usage of the body keyword has been deprecated
- Deprecate a case of using fully-qualified names to bypass imports
- Explicit package visibility attribute is now always applied to new scopes
- pragma(mangle) can now be applied to aggregates
- Complex and imaginary types are now deprecated
- while (auto n = expression) is now supported
Library changes
- Centering formatted output.
- AllImplicitConversionTargets replaces ImplicitConversionTargets
- Formatting integers with %e, %f, %g and %a is now possible.
- Implementation of pow(f, -2) and f ^^ -2 changed
- Deprecate std.format : enforceValidFormatSpec
- Deprecate std.format : formatElement
- Deprecate std.format : unformatElement
- FieldnameTuple now returns an empty tuple for interfaces
- Fields (formerly FieldTypeTuple) now returns an empty tuple for interfaces
- Floating point numbers can be formatted at compile time
- Formatting floating point numbers don't allocate with the GC anymore.
- Some reals will be downcast to double when used with std.format.
- std.typecons.Nullable: Remove deprecated alias get this.
- Documentation of std.format has been completely reworked.
- Module std.format has been split into smaller modules
- Module std.math has been split into smaller modules
- splitWhen added to std.algorithm.iteration
- The old benchmarking functionality in std.datetime has been removed.
- std.exception.enforceEx has been removed.
- New module: std.sumtype
- std.range.Transposed: Remove deprecated member save
List of all bug fixes and enhancements in D 2.097.0.
Compiler changes
- Deprecation period for ambiguous ternary expressions has ended
In D, the ternary operator (?:) has a higher precedence than the assignment operator (=), hence:
true ? stt = "AA" : stt = "BB"
actually means:
(true ? (stt = "AA") : stt) = "BB",
This is in line with C, and many other languages (except C++), but comes at a surprise to many, which is why this specific combination of ternary and assignment was deprecated in v2.082.0 (2018-09-01).
The deprecation instructs the user to use parenthesis to make the intent explicit, so the above snippet should read as:
true ? (stt = "AA") : (stt = "BB")
This deprecation period has now ended and the compiler will now issue an error for ambiguous code.
- Usage of the body keyword has been deprecated
Using body to indicate the body of a function or method in the presence of contracts is now deprecated. Any leftover usage of body can be replaced with do. This replacement, introduced by DIP1003, has been available since DMD v2.075.0 (July 2017).
- Deprecate a case of using fully-qualified names to bypass imports
Since v2.084 it is no longer possible to bypass private imports by using fully-qualified names, this was deprecated in v2.071 but when fully-qualified names are used as a type (vs an expression) the code is accepted without any warning.
Starting with this release the compiler will now properly deprecate the previous omitted case.
The issue is best described in the following example:
import std.algorithm; // deprecated in v2.071, error since v2.084 auto a = std.range.Take!(int[]); // Error: undefined identifier `range` in package `std`... // now it's deprecated, will be error from v2.106 std.range.Take!(int[]) s;
- Explicit package visibility attribute is now always applied to new scopes
If a less restrictive package attribute appeared within the scope of another package attribute, the more restrictive parent would override any explicit child visibility.
Example:
module pkg.foo; package(pkg.foo): // analogous to "private" or plain "package" package(pkg) int bar(); // package(pkg) was being ignored
Starting from this version, the package visibility attribute is now always applied as long as it is valid. In the given example, this allows any module in the package pkg to import and use the symbol bar.
- pragma(mangle) can now be applied to aggregates
The syntax is pragma(mangle, str_or_decl [, str] ) declaration; where str_or_decl is either: a string expression to substitute the name of declaration; or a class, struct, or union declaration or template instance to use instead of declarations for mangling. If the optional second argument is present, use that as a name instead but keep the namespaces and template parameters of str_or_decl (if any).
This enables binding with functions that take classes by value or reference and to classes that are D keywords.
To bind C++'s std::function by value:
extern(C++, "std") { template std_function(F) { pragma(mangle, "function") class std_function { // member variables and functions } } } template ScopeClass(C , string name) { enum ns = __traits(getCppNamespaces,C); extern(C++, class) extern(C++,(ns)) { pragma(mangle, C, name) struct ScopeClass { char[__traits(classInstanceSize, C)] buffer; // member variables and functions } } } alias FuncType = void function(int); alias RawFuncType = typeof(*FuncType.init); // Mangles as `void funk(std::function<void(int)> a)` extern(C++) void funk( ScopeClass!(std_function!(RawFuncType)),"function") a );
- Complex and imaginary types are now deprecated
D previously supported complex and imaginary versions of all floating point types as part of the language.
float a = 2; ifloat b = 4i; cfloat c = a + b; assert(c == 2 + 4i);
However these types are too specialized to be a part of the core language, and the same functionalities can be implemented as part of a library type. As such, older versions of DMD provided the -transition=complex switch to warn when those builtin types were used. This transition phase has finished, and those deprecations are now turned on by default.
Users should use std.complex.Complex instead.
import std.complex; float a = 2; float b = 4; auto c = complex(a, b); assert(c == complex(2, 4));
The -transition=complex switch that previously turn on deprecation warnings no longer has an effect and has also been deprecated.
- while (auto n = expression) is now supported
Up until this release, while (auto n = expression) was not supported, although the if counterpart: if (auto n = expression) compiled succesfully. Starting with the current compiler version, while (auto n = expression) is accepted, having the exact same semantics as:
while (true) { if (auto n = expression) { /* loop body */ } else { break; } }
Library changes
- Centering formatted output.
A new flag '=' has been added to the format specifier, which allows to center the output:
assert(format!"|%=8d|"(1234) == "| 1234 |");
In case the output cannot be centered exactly it is moved slightly to the left if '-' flag is present too and to the right else:
assert(format!"|%=-8d|"(123) == "| 123 |"); assert(format!"|%=8d|"(123) == "| 123 |");
- AllImplicitConversionTargets replaces ImplicitConversionTargets
The function ImplicitConversionTargets in module std.traits has a design flaw: The list of conversion targets contains some, but not all unsafe conversion targets. To overcome this, a new function AllImplicitConversionTargets has been added and ImplicitConversionTargets has been deprecated.
- Formatting integers with %e, %f, %g and %a is now possible.
The formatting posibilities of integers have been expanded to the specifiers that are typical for floating point numbers: Integers can now be formatted using %e, %f, %g and %a. The result is similar to the result expected for the corresponding floating point value.
assert(format!"%.3e"(ulong.max) == "1.845e+19"); assert(format!"%.3,3f"(ulong.max) == "18,446,744,073,709,551,615.000"); assert(format!"%.3g"(ulong.max) == "1.84e+19"); assert(format!"%.3a"(ulong.max) == "0x1.000p+64");
- Implementation of pow(f, -2) and f ^^ -2 changed
We noticed that the implementation of pow(f, -2) and f ^^ -2 with f being a floating point value, was buggy for some values of f. Unfortunately the fix implies small changes for other values for f (with exponent -2) too: The least significant bits of the result might differ from the current implementation. (This is due to the peculiarities of floating point numbers and cannot be avoided with reasonable means.)
To avoid problems, make sure, that your algorithms do not rely on the least significant bits of floating point calculations, for example by using isClose instead of ==.
- Deprecate std.format : enforceValidFormatSpec
enforceValidFormatSpec from std.format has been accidentally made public and will be removed from public view in 2.107.0.
- Deprecate std.format : formatElement
formatElement from std.format has been accidentally made public and will be removed from public view in 2.107.0.
Please use instead of formatElement(sink, value, fmt):
import std.range : only; sink.put(format!("%("~fmt~"%)")(only(value)));
- Deprecate std.format : unformatElement
unformatElement from std.format has been accidentally made public and will be removed from public view in 2.107.0.
Please use instead for strings and characters parseElement from std.conv and for all else unformatValue from std.format.read.
- FieldnameTuple now returns an empty tuple for interfaces
Previously FieldNameTuple returned AliasSeq!"" for interfaces as done for non-aggregate types like int, char*, ... . This behaviour was surprising because an instance of that interface may have members that just are not known at compile time.
FieldNameTuple will now return an empty AliasSeq!() for interfaces.
- Fields (formerly FieldTypeTuple) now returns an empty tuple for interfaces
Previously Fields returned AliasSeq!(Interface) for interfaces as done for non-aggregate types like int, char*, ... . This behaviour was surprising because an instance of an interface may have members that just are not known at compile time.
Fields will now return an empty AliasSeq!() for interfaces.
- Floating point numbers can be formatted at compile time
Example:
import std.format : format; import std.math : sqrt; enum pi = format!"%s"(3.1415926f); static assert(pi == "3.14159"); enum golden_ratio = format!"|%+-20.10E|"((1 + sqrt(5.0)) / 2); static assert(golden_ratio == "|+1.6180339887E+00 |");
- Formatting floating point numbers don't allocate with the GC anymore.
The implementation of formatting floating point numbers has been reworked. We made sure that working examples never allocate with the GC, however, we are still using exceptions which are GC managed. Therefore, code that uses formatting correctly will never allocate, but in the case of exceptions, the GC will be used to allocate the exception. We are working on DIP 1008 to solve this issue.
- Some reals will be downcast to double when used with std.format.
In the internals of std.format we replaced a call to snprintf of libc with routines written in D for formatting floating point values. These functions only work for floats, doubles, 64-bit-reals and 80-bit-reals (x87-reals) yet.
All other reals are handled by downcasting them to doubles before being formatted. This might result in a loss of precision in the output. Further, numbers larger than double.max will be formatted like double.max and numbers large than zero but smaller than the smallest positive double will be formatted like the smallest positive double. Likewise for negative values.
- std.typecons.Nullable: Remove deprecated alias get this.
Nullable no longer implicitly converts to its member. This feature was problematic because a simple use of a value could invisibly cause an assertion due to type conversion. To restore the previous behavior, replace uses of a Nullable value n with n.get.
- Documentation of std.format has been completely reworked.
In the last years, the documentation of std.format was outdated little by little and therefore needed a complete rework. The whole package was reviewed and all documentations, including examples, improved and extended.
Some highlights:
- The grammar of the format string was updated.
- A detailed description of format specifiers was provided.
- Several examples on how to use the functions and the format strings were added.
- Module std.format has been split into smaller modules
The module std.format has been split into submodules:
- std.format.spec: Symbols concerning the format string, mainly the struct FormatSpec and the template singleSpec
- std.format.read: Symbols concerning reading input, mainly the template formattedRead and the template unformatValue
- std.format.write: Symbols concerning writing output, mainly the template formattedWrite and the template formatValue
All public symbols are still accessible using std.format as usual.
- Module std.math has been split into smaller modules
The module std.math has been split into submodules:
- std.math.constants: Mathematical constants, like PI.
- std.math.algebraic: Basic algebraic functions, like abs and sqrt.
- std.math.trigonometry: Trigonometric functions, like sin and cos.
- std.math.rounding: Functions concerned about rounding, like ceil and floor.
- std.math.exponential: Exponential and logarithmic functions, like pow, exp and log.
- std.math.remainder: Function calculating the remainder, like fmod.
- std.math.operations: Floating-point operations, like isClose, nextUp and fmin.
- std.math.traits: Floating-point introspection, like isNaN and isSubnormal.
- std.math.hardware: Hardware control: IeeeFlags and FloatingPointControl.
All public symbols are still accessible using std.math as usual.
- splitWhen added to std.algorithm.iteration
std.algortihm.iteration.splitWhen is a variant of the existing std.algortihm.iteration.chunkBy function that does not require its predicate to be an equivalence relation, allowing it to be used in ways that chunkBy cannot. For example:
// Grouping by maximum adjacent difference: import std.math : abs; import std.algorithm; auto r3 = [1, 3, 2, 5, 4, 9, 10].splitWhen!((a, b) => abs(a-b) >= 3); assert(r3.equal!equal([ [1, 3, 2], [5, 4], [9, 10] ]));
This would have an undefined result with chunkBy, because it requires that if pred(a,b) and pred(b,c) return true, pred(a,c) must also return true.
- The old benchmarking functionality in std.datetime has been removed.
It had been deprecated in 2.077.0 in favor of std.datetime.stopwatch, which uses core.time.MonoTime and core.time.Duration.
- std.exception.enforceEx has been removed.
It had been deprecated in 2.079 in favor of std.exception.enforce.
- New module: std.sumtype
The sumtype package from code.dlang.org has been added to the standard library as std.sumtype.
It provides SumType, a generic discriminated union implementation that uses design-by-introspection to generate safe and efficient code, and is intended to serve as a replacement for the legacy std.variant.Algebraic.
Features of SumType include:
- Pattern matching.
- Support for self-referential types.
- Full compatibility with pure, @safe, @nogc, nothrow, and scope.
- No dependency on runtime type information (TypeInfo).
- Compatibility with BetterC.
Example usage:
import std.sumtype; import std.math : isClose; struct Fahrenheit { double degrees; } struct Celsius { double degrees; } struct Kelvin { double degrees; } alias Temperature = SumType!(Fahrenheit, Celsius, Kelvin); // Construct from any of the member types. Temperature t1 = Fahrenheit(98.6); Temperature t2 = Celsius(100); Temperature t3 = Kelvin(273); // Use pattern matching to access the value. Fahrenheit toFahrenheit(Temperature t) { return Fahrenheit( t.match!( (Fahrenheit f) => f.degrees, (Celsius c) => c.degrees * 9.0/5 + 32, (Kelvin k) => k.degrees * 9.0/5 - 459.4 ) ); } assert(toFahrenheit(t1).degrees.isClose(98.6)); assert(toFahrenheit(t2).degrees.isClose(212)); assert(toFahrenheit(t3).degrees.isClose(32)); // Use ref to modify the value in place. void freeze(ref Temperature t) { t.match!( (ref Fahrenheit f) => f.degrees = 32, (ref Celsius c) => c.degrees = 0, (ref Kelvin k) => k.degrees = 273 ); } freeze(t1); assert(toFahrenheit(t1).degrees.isClose(32)); // Use a catch-all handler to give a default result. bool isFahrenheit(Temperature t) { return t.match!( (Fahrenheit f) => true, _ => false ); } assert(isFahrenheit(t1)); assert(!isFahrenheit(t2)); assert(!isFahrenheit(t3));
- std.range.Transposed: Remove deprecated member save
Transposed never worked as forward range.
Dub changes
- Added support for low memory compilation option to the dub settings file.
To enable, set defaultLowMemory to true. For dmd and ldc, the -lowmem command-line option is added when compiling.
{ "defaultLowMemory": true }
List of all bug fixes and enhancements in D 2.097.0:
DMD Compiler regression fixes
- Bugzilla 21752: Template constraint breaks nested eponymeous template
- Bugzilla 21802: opAssign and opOpAssign treat lazy void parameters inconsistently
- Bugzilla 21880: [REG 2.095] scope variable assigned to non-scope parameter calling function
- Bugzilla 21898: Qualifier ignored in alias definition if parentheses are not present
- Bugzilla 21914: naked assembler functions get wrong offset to parameters
- Bugzilla 21936: [REG 2.080.1] Segfault when compiled with -dip1000
DMD Compiler bug fixes
- Bugzilla 2450: Error using operators from named template mixin
- Bugzilla 13815: Inconsistent goto jump behavior between compile-time and runtime
- Bugzilla 14114: Allow volatileLoad/Store to access null location
- Bugzilla 14145: opDispatch not considered when function body doesn't compile
- Bugzilla 14740: __traits(allMembers) returns erroneous 'this' member for types declared in functions.
- Bugzilla 14954: extern opaque struct instance doesn't compile
- Bugzilla 15478: cases of missed CTFE evaluation when defining arrays dimensions
- Bugzilla 16472: Spurious "is used as a type" when aliasing enum template as default parameter
- Bugzilla 17146: Internal error: tk.c 266 with -O -inline
- Bugzilla 18251: deprecate + transition=complex shouldn't look at functions with non-matching if constraints
- Bugzilla 19387: [dip1000] __fieldPostblit should be scope or deduce scope qualifier
- Bugzilla 19443: core.simd generates MOVLPS instead of MOVHLPS
- Bugzilla 19783: Fail to emplace struct with betterC
- Bugzilla 20460: [OSX] DMD writes the same address everywhere in DWARF debug infos
- Bugzilla 20581: DIP1000 wrongly flags hidden ref temporary
- Bugzilla 20599: cpp_long as enum type doesn't work
- Bugzilla 20704: -preview=rvaluerefparam does not work with init as default parameter
- Bugzilla 20855: stack overflow when compiling large file
- Bugzilla 21403: dmd/backend/cgcs.d:375 assert failed
- Bugzilla 21651: Unimported package doesn't error out when used as part of fully qualified type
- Bugzilla 21661: Can't use fully-qualified name of the current module inside an expression
- Bugzilla 21665: Void initialization should not be allowed for instances of struct with invariant
- Bugzilla 21668: Cannot declare ref parameter of opaque type
- Bugzilla 21672: [REG][ICE][SIMD] accessing SIMD type as a short causes compiler ice
- Bugzilla 21680: inconsistent error on typeof({ return field; }())
- Bugzilla 21684: Assert fail for Win32 with a struct larger than 64k in size
- Bugzilla 21699: Duplicate error for index out of bounds at compile time
- Bugzilla 21726: Wrong comparison in package(...) visibilities
- Bugzilla 21739: debug case can access variable from other case
- Bugzilla 21742: dot template expressions don't have the void type like any template
- Bugzilla 21743: getOverloads fails to propagate 'this' expression for template member
- Bugzilla 21753: Struct literal with function literal member not allowed as template value argument
- Bugzilla 21765: Assignment-as-condition error with checkaction=context
- Bugzilla 21779: assert not omitted for -release -checkaction=context
- Bugzilla 21785: Cannot declare variable of opaque enum with base type
- Bugzilla 21791: Stack overflow for forward-referenced enum initializer
- Bugzilla 21792: Enum using itself as base type crashes dmd
- Bugzilla 21793: Cannot initialize shared member with -preview=nosharedaccess
- Bugzilla 21797: Stack overflow for forward-referenced enum min / max
- Bugzilla 21812: __traits(allMembers) on types with value tuples return ghost members
- Bugzilla 21816: testing XMM for nan does not work
- Bugzilla 21822: Optimizer flowlv() does not account for OPmemcmp and OPstrcmp
- Bugzilla 21825: DIP1034: Do not spuriously warn "calling XXX without side effects discards return value of type 'noreturn'"
- Bugzilla 21826: MSCOFF output for Win32 should not use EBP for anything other than the frame pointer
- Bugzilla 21827: Null pointer exception in elToPair() in backend/cgelem.d
- Bugzilla 21828: Enum forward-references just assume int base type
- Bugzilla 21830: Wrong deprecation message when non-deprecated template in static condition
- Bugzilla 21831: Wrong deprecation message in template parameters before evaluating constraints
- Bugzilla 21832: Wrong deprecation message when importing non-deprecated template in static condition
- Bugzilla 21833: Optimizer incorrectly rewrites integer comparison to unsigned short comparison
- Bugzilla 21849: UTF8: -verrors=context doesn't respect multibyte characters
- Bugzilla 21861: ctfe fails when a nested enum or function has a UDA
- Bugzilla 21870: Property/method not invoked and requires () when used in static array length
- Bugzilla 21874: The test suite fails with most recent GDB versions
- Bugzilla 21876: Zero-length static arrays "cannot be read at compile time"
- Bugzilla 21878: "ref" lost when indexing array in CTFE
- Bugzilla 21882: [ICE][dip1021] src/dmd/escape.d(1850): Assertion failure
- Bugzilla 21883: poor error message when swapping order of base class and interface
- Bugzilla 21918: segfault in getParameterStorageClasses on auto function with error
- Bugzilla 21927: ICE (illegal instruction) with static foreach over empty member template
- Bugzilla 21940: Compiler flags -check=on/off not recognized
DMD Compiler enhancements
- Bugzilla 16140: while(auto x = y) does not behave like if(auto x = y)
- Bugzilla 20068: Union initialization in constructors should be @safe
- Bugzilla 21203: Accept pragma(mangle) on aggregate types
- Bugzilla 21585: add __traits(totype, string) to convert mangled type string to an existing type
- Bugzilla 21630: assert(0) and assert(false) should not be marked for coverage
- Bugzilla 21835: Operation on float should use XMM register, not x87
Phobos regression fixes
- Bugzilla 21716: std.regex performance regression (additional GC allocation)
- Bugzilla 21725: Specifying null as bitfields variable name now fails
Phobos bug fixes
- Bugzilla 8424: Compile time conversions of double/floats to strings
- Bugzilla 9297: Formatting of floating point values in std.format truncates reals to double
- Bugzilla 15227: std.format undocumented grammar
- Bugzilla 15348: std.stdio.writef format specifier error message
- Bugzilla 15386: std.format.formatValue usage hangs
- Bugzilla 15888: std.format should not produce deprecated hexstrings
- Bugzilla 16432: JSON incorrectly parses to string
- Bugzilla 17381: Checked format string is permissive after floating point argument
- Bugzilla 18780: Inconsistent behavior with Variant holding int converting to unsigned types
- Bugzilla 20320: format("%f") leeds to wrong output
- Bugzilla 20371: std.format limited to 500 characters for floats
- Bugzilla 20502: Converting std.typecons.RefCounted!T to a string gives T's storage location instead of T's fields when T is a struct without an explicit toString
- Bugzilla 20534: std.format: %r on boolean gives wrong result
- Bugzilla 20536: std.format: %a on reals is inconsistent with %a on float/double
- Bugzilla 21456: std.format does not accept enum member with string base type as template parameter
- Bugzilla 21512: RedBlackTree!Tid treats any values as duplicated except for Tid.init
- Bugzilla 21575: Child processes spawned by std.process.spawnProcess accidentally inherit signal masks in parent process
- Bugzilla 21592: two stack traces if high surrogate is printed
- Bugzilla 21601: std.math : pow(float/double, -2) produces sometimes wrong result
- Bugzilla 21627: macOS: std.stdio.File.sync does not guarantee to be written to disk
- Bugzilla 21641: std.format: %g produces in rare circumstances inconsistent result
- Bugzilla 21679: Assertion failure in Base64.encoder for empty input range of ranges
- Bugzilla 21700: Long deprecated Stopwatch std.datetime is still not removed
- Bugzilla 21702: avoid quadratic template expansion in constraints of multiple search term versions of std.algorithm.searching.startsWith & endsWith
- Bugzilla 21704: Nullable fails to destroy static array elements
- Bugzilla 21705: Nullable!T.opEquals fails for T with non-const opEquals overload
- Bugzilla 21707: std.base64: Faulty input creates range error instead of Base64Exception
- Bugzilla 21708: SumType.opEquals gives confusing error message
- Bugzilla 21721: casting std.BigInts to built-in floating point types doesn't work without -preview=dip1000
- Bugzilla 21722: toString(sink, string format) does not work with non-"%s" strings
- Bugzilla 21724: std.algorithm.mutation.copy fails on overlapping arrays if the source array's pointer is less than the destination array's pointer
- Bugzilla 21728: rawRead calls fread with NULL if invoked on closed readEnd of Pipe (segfault)
- Bugzilla 21729: rawRead derefences null pointer if invoked on closed File (segfault)
- Bugzilla 21730: null ptr dereferenced in ChunksImpl.opApply (SIGSEGV)
- Bugzilla 21738: std.format.spec: singleSpec should throw on "%%"
- Bugzilla 21758: std.experimental.checkedint opBinaryRight with integer left-hand side does not compile for any operators except + and -
- Bugzilla 21777: std.format: several issues when formatting integers with precision
- Bugzilla 21814: std.format: grouping with width 0 causes floating point exception
- Bugzilla 21817: std.format: %u on integer does not print unsigned value
- Bugzilla 21820: std.format: formatting zero should never lead to empty string
- Bugzilla 21834: std.numeric.gcd can't handle negative values
- Bugzilla 21836: std.format: grouping may cause RangeError
- Bugzilla 21838: std.format: Grouping garbles up %a output
- Bugzilla 21840: std.format: grouping ignores space flag with %e
- Bugzilla 21841: std.format: grouping produces strange result with zero precision and %e
- Bugzilla 21842: std.format: "%-+05,g" adds extra comma
- Bugzilla 21846: std.format: provided format string for toString does not work with grouping
- Bugzilla 21853: std.format: formatting real.max in CTFE fails
- Bugzilla 21863: FieldNameTuple returns emptry string for interfaces
- Bugzilla 21875: std.format: wrong number of format specifiers in nested format string of associative arrays should be detected
- Bugzilla 21900: std.format: round to even does not work for hex integers with letters
Phobos enhancements
- Bugzilla 13595: Extend std.algorithm.groupBy to support non-equivalence relations
- Bugzilla 16200: Faster pow implementation for integral exponents
- Bugzilla 18024: checkedint.Abort and checkedint.Warn should be @safe
- Bugzilla 18627: std.complex is a lot slower than builtin complex types at number crunching
- Bugzilla 20756: ImplicitConversionTargets ignores interface inheritance
- Bugzilla 21759: std.experimental.checkedint.Checked is not compatible with "%d" and "%x" integer format specifiers
- Bugzilla 21760: std.conv.to does not know how to convert a string to a std.experimental.checkedint.Checked!T
- Bugzilla 21761: make std.experimental.checkedint.Checked!T.toHash callable when Checked!T is shared
- Bugzilla 21808: std.format: It should be possible to change the order of key and value of AAs.
- Bugzilla 21847: std.format: %e, %g and %a should be supported for integers too
- Bugzilla 21858: std.format: centering output
Druntime regression fixes
- Bugzilla 21097: [REG2.083] Stack exhaustion upon large struct .destroy
- Bugzilla 21363: [REG2.094] Implementation of core.bitop.ror(x,0) is using UB
Druntime bug fixes
- Bugzilla 21764: checkaction=context doesn't work for empty tuples
- Bugzilla 21857: TypeInfo_Array.compare can give wrong result when either array exceeds 2GB
Druntime enhancements
- Bugzilla 21789: Codecov should use default umask for file permissions
dlang.org enhancements
- Bugzilla 21161: [Variadic Templates] uses outdated example from D1 / Tango
- Bugzilla 21869: Invalid hyperlink to doxygen
Contributors to this release (54)
A huge thanks goes to all the awesome people who made this release possible.
- Adam D. Ruppe
- aG0aep6G
- Airbus5717
- Andrei Alexandrescu
- Andrej Petrović
- Arne
- Ate Eskola
- Atila Neves
- Basile Burg
- berni44
- Boris Carvajal
- Brian Callahan
- Chigusa0w0
- dkorpel
- DoctorNoobingstoneIPresume
- Florian
- Hiroki Noda
- Iain Buclaw
- Imperatorn
- Jason B. Cox
- Johan Engelen
- Jon Degenhardt
- linkrope
- Lucien Perregaux
- Luhrel
- Luís Ferreira
- Martin Kinkelin
- Martin Nowak
- Mathias Lang
- Mathis Beer
- Max Haughton
- MetaLang
- mhh
- Mike Parker
- MoonlightSentinel
- Nathan Sashihara
- Nicholas Wilson
- Nick Treleaven
- nordlow
- Paul Backus
- Per Nordlöw
- Razvan Nitu
- Robert Aron
- Robert Schadek
- Roy Margalit
- Sebastian Wilzbach
- Stefan Koch
- Tobias Pankrath
- Tomoya Tanjo
- Vladimir Panteleev
- Walter Bright
- Witold Baryluk
- wolframw
- Ömer Faruk IRMAK