diff --git a/changelog/log_float_double_implementations.dd b/changelog/log_float_double_implementations.dd deleted file mode 100644 index 81a8c4d21..000000000 --- a/changelog/log_float_double_implementations.dd +++ /dev/null @@ -1,15 +0,0 @@ -Single- and double-precision implementations for log function families - -New `float` and `double` overloads of $(REF log, std, math, exponential), -$(REF log10, std, math, exponential), $(REF log1p, std, math, exponential), - $(REF log2, std, math, exponential), and $(REF logb, std, math, exponential) -have been added to Phobos with proper 'software' implementations in the -corresponding precision. Furthermore, $(REF logb, std, math, exponential) 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. diff --git a/changelog/unicode_properties_c.dd b/changelog/unicode_properties_c.dd deleted file mode 100644 index cafaf54da..000000000 --- a/changelog/unicode_properties_c.dd +++ /dev/null @@ -1,24 +0,0 @@ -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](https://www.unicode.org/reports/tr44/). 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; -} ---- diff --git a/changelog/unicode_table_generator.dd b/changelog/unicode_table_generator.dd deleted file mode 100644 index 65851d041..000000000 --- a/changelog/unicode_table_generator.dd +++ /dev/null @@ -1,5 +0,0 @@ -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. - diff --git a/changelog/unique-struct-dtor.dd b/changelog/unique-struct-dtor.dd deleted file mode 100644 index d8bf38a73..000000000 --- a/changelog/unique-struct-dtor.dd +++ /dev/null @@ -1,28 +0,0 @@ -`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. - -$(RUNNABLE_EXAMPLE ---- -static int i; - -struct S -{ - ~this() - { - i++; - } -} -{ - Unique!S u = new S; - // S.~this now called here -} -assert(i == 1); ---- -) - -$(B 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. diff --git a/std/typecons.d b/std/typecons.d index 25cf9e008..bde8439a5 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -3159,12 +3159,6 @@ struct Nullable(T) return this; } - /// ditto - inout(typeof(this)) opIndex() inout - { - return this; - } - /// ditto inout(typeof(this)) opIndex(size_t[2] dim) inout in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0]) @@ -3192,6 +3186,74 @@ struct Nullable(T) { return get(); } + + /** + * Converts `Nullable` to a range. Works even when the contained type is `immutable`. + */ + auto opSlice(this This)() + { + static struct NullableRange + { + private This value; + + // starts out true if value is null + private bool empty_; + + @property bool empty() const @safe pure nothrow + { + return empty_; + } + + void popFront() @safe pure nothrow + { + empty_ = true; + } + + alias popBack = popFront; + + @property ref inout(typeof(value.get())) front() inout @safe pure nothrow + { + return value.get(); + } + + alias back = front; + + @property inout(typeof(this)) save() inout + { + return this; + } + + size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const + { + return [from, to]; + } + + @property size_t length() const @safe pure nothrow + { + return !empty; + } + + alias opDollar(size_t dim : 0) = length; + + ref inout(typeof(value.get())) opIndex(size_t index) inout @safe pure nothrow + in (index < length) + { + return value.get(); + } + + inout(typeof(this)) opIndex(size_t[2] dim) inout + in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0]) + { + return (dim[0] == 0 && dim[1] == 1) ? this : this.init; + } + + auto opIndex() inout + { + return this; + } + } + return NullableRange(this, isNull); + } } /// ditto @@ -3774,6 +3836,34 @@ auto nullable(T)(T t) assert(hasLvalueElements!(Nullable!int)); } +// https://issues.dlang.org/show_bug.cgi?id=23640 +@safe pure nothrow unittest +{ + import std.algorithm.comparison : equal; + import std.range : only; + import std.range.primitives : hasLength, hasSlicing, + isRandomAccessRange; + static immutable struct S { int[] array; } + auto value = S([42]); + alias ImmutableNullable = immutable Nullable!S; + auto a = ImmutableNullable(value)[]; + alias Range = typeof(a); + assert(isRandomAccessRange!Range); + assert(hasLength!Range); + assert(hasSlicing!Range); + assert(!a.empty); + assert(a.front == value); + assert(a.back == value); + assert(a[0] == value); + assert(a.equal(only(value))); + assert(a[0 .. $].equal(only(value))); + Range b = a.save(); + assert(!b.empty); + b.popFront(); + assert(!a.empty); + assert(b.empty); +} + /** Just like `Nullable!T`, except that the null state is defined as a particular value. For example, $(D Nullable!(uint, uint.max)) is an