Merge remote-tracking branch 'upstream/stable' into merge_stable

This commit is contained in:
Iain Buclaw 2023-02-01 20:32:15 +00:00
commit 1f49f65c51
5 changed files with 96 additions and 78 deletions

View file

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

View file

@ -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;
}
---

View file

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

View file

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

View file

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