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

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