summaryrefslogtreecommitdiff
path: root/libphobos/src/std/range/package.d
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos/src/std/range/package.d')
-rw-r--r--libphobos/src/std/range/package.d291
1 files changed, 260 insertions, 31 deletions
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index 30f6ffb9f44..995bf1e6c9b 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -313,16 +313,18 @@ if (isBidirectionalRange!(Unqual!Range))
{
@property void front(ElementType!R val)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- source.back = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source.back = __ctfe ? val : forward!val;
}
@property void back(ElementType!R val)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- source.front = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source.front = __ctfe ? val : forward!val;
}
}
@@ -334,9 +336,10 @@ if (isBidirectionalRange!(Unqual!Range))
{
void opIndexAssign(ElementType!R val, size_t n)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- source[retroIndex(n)] = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source[retroIndex(n)] = __ctfe ? val : forward!val;
}
}
@@ -494,6 +497,32 @@ pure @safe nothrow unittest
assert(equal(r, [S(3), S(2), S(1)]));
}
+// https://issues.dlang.org/show_bug.cgi?id=24481
+@safe unittest
+{
+ bool called;
+ struct Handle
+ {
+ int entry;
+ void opAssign()(auto ref const(typeof(this)) that) const { called = true; }
+ }
+
+ const(Handle)[5] arr = [Handle(0), Handle(1), Handle(2), Handle(3), Handle(4)];
+ auto range = arr[].retro();
+
+ called = false;
+ range.front = Handle(42);
+ assert(called);
+
+ called = false;
+ range.back = Handle(42);
+ assert(called);
+
+ called = false;
+ range[2] = Handle(42);
+ assert(called);
+}
+
/**
Iterates range `r` with stride `n`. If the range is a
random-access range, moves by indexing into the range; otherwise,
@@ -604,9 +633,10 @@ do
{
@property void front(ElementType!R val)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- source.front = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source.front = __ctfe ? val : forward!val;
}
}
@@ -899,6 +929,24 @@ pure @safe nothrow unittest
assert(equal(r, [S(1), S(4)]));
}
+// https://issues.dlang.org/show_bug.cgi?id=24481
+@safe unittest
+{
+ bool called;
+ struct Handle
+ {
+ int entry;
+ void opAssign()(auto ref const(typeof(this)) that) const { called = true; }
+ }
+
+ const(Handle)[5] arr = [Handle(0), Handle(1), Handle(2), Handle(3), Handle(4)];
+ auto range = arr[].stride(2);
+
+ called = false;
+ range.front = Handle(42);
+ assert(called);
+}
+
/**
Spans multiple ranges in sequence. The function `chain` takes any
number of ranges and returns a $(D Chain!(R1, R2,...)) object. The
@@ -1120,14 +1168,15 @@ if (Ranges.length > 0 &&
@property void front(RvalueElementType v)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
sw: switch (frontIndex)
{
static foreach (i; 0 .. R.length)
{
case i:
- source[i].front = move(v);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source[i].front = __ctfe ? v : forward!v;
break sw;
}
@@ -1246,14 +1295,15 @@ if (Ranges.length > 0 &&
{
@property void back(RvalueElementType v)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
sw: switch (backIndex)
{
static foreach_reverse (i; 1 .. R.length + 1)
{
case i:
- source[i-1].back = move(v);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source[i - 1].back = __ctfe ? v : forward!v;
break sw;
}
@@ -1359,7 +1409,7 @@ if (Ranges.length > 0 &&
static if (allSameType && allSatisfy!(hasAssignableElements, R))
void opIndexAssign(ElementType v, size_t index)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
sw: switch (frontIndex)
{
@@ -1376,7 +1426,8 @@ if (Ranges.length > 0 &&
}
}
- source[i][index] = move(v);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source[i][index] = __ctfe ? v : forward!v;
break sw;
}
@@ -1683,7 +1734,7 @@ pure @safe unittest
assert(range.array == [S(5), S(6)]);
}
-/// https://issues.dlang.org/show_bug.cgi?id=24064
+// https://issues.dlang.org/show_bug.cgi?id=24064
pure @safe nothrow unittest
{
import std.algorithm.comparison : equal;
@@ -1716,7 +1767,7 @@ pure @safe nothrow @nogc unittest
}
}
-/// https://issues.dlang.org/show_bug.cgi?id=24243
+// https://issues.dlang.org/show_bug.cgi?id=24243
pure @safe nothrow unittest
{
import std.algorithm.iteration : filter;
@@ -1727,6 +1778,32 @@ pure @safe nothrow unittest
assert(typeof(range).init.empty);
}
+// https://issues.dlang.org/show_bug.cgi?id=24481
+@safe unittest
+{
+ bool called;
+ struct Handle
+ {
+ int entry;
+ void opAssign()(auto ref const(typeof(this)) that) const { called = true; }
+ }
+
+ const(Handle)[5] arr = [Handle(0), Handle(1), Handle(2), Handle(3), Handle(4)];
+ auto range = arr[0 .. 2].chain(arr[4 .. 5]);
+
+ called = false;
+ range.front = Handle(42);
+ assert(called);
+
+ called = false;
+ range.back = Handle(42);
+ assert(called);
+
+ called = false;
+ range[2] = Handle(42);
+ assert(called);
+}
+
/**
Choose one of two ranges at runtime depending on a Boolean condition.
@@ -1882,7 +1959,7 @@ private struct ChooseResult(Ranges...)
this(this)
{
actOnChosen!((ref r) {
- static if (hasElaborateCopyConstructor!(typeof(r))) r.__postblit();
+ static if (hasElaborateCopyConstructor!(typeof(r))) r.__xpostblit();
})(this);
}
@@ -2177,6 +2254,29 @@ pure @safe nothrow unittest
assert(chosen2.front.v == 4);
}
+// https://issues.dlang.org/show_bug.cgi?id=15708
+@safe unittest
+{
+ static struct HasPostblit
+ {
+ this(this) {}
+ }
+
+ static struct Range
+ {
+ bool empty;
+ int front;
+ void popFront() {}
+ HasPostblit member;
+ }
+
+ Range range;
+ int[] arr;
+
+ auto chosen = choose(true, range, arr);
+ auto copy = chosen;
+}
+
/**
Choose one of multiple ranges at runtime.
@@ -2694,12 +2794,14 @@ if (isInputRange!(Unqual!Range) &&
/// ditto
@property void front(ElementType!R v)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
assert(!empty,
"Attempting to assign to the front of an empty "
~ Take.stringof);
- source.front = move(v);
+
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ source.front = __ctfe ? v : forward!v;
}
static if (hasMobileElements!R)
@@ -2996,6 +3098,25 @@ pure @safe nothrow @nogc unittest
assert(r.take(2).equal(repeat(1, 2)));
}
+// https://issues.dlang.org/show_bug.cgi?id=24481
+@safe unittest
+{
+ import std.algorithm.iteration : filter;
+
+ bool called;
+ struct Handle
+ {
+ int entry;
+ void opAssign()(auto ref const(typeof(this)) that) const { called = true; }
+ }
+
+ const(Handle)[5] arr = [Handle(0), Handle(1), Handle(2), Handle(3), Handle(4)];
+ auto range = arr[].filter!(a => true)().take(3);
+
+ called = false;
+ range.front = Handle(42);
+ assert(called);
+}
/**
Similar to $(LREF take), but assumes that `range` has at least $(D
@@ -3075,12 +3196,14 @@ if (isInputRange!R)
{
@property auto ref front(ElementType!R v)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
assert(!empty,
"Attempting to assign to the front of an empty "
~ typeof(this).stringof);
- return _input.front = move(v);
+
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ return _input.front = __ctfe ? v : forward!v;
}
}
}
@@ -3217,6 +3340,26 @@ pure @safe nothrow unittest
}}
}
+// https://issues.dlang.org/show_bug.cgi?id=24481
+@safe unittest
+{
+ import std.algorithm.iteration : filter;
+
+ bool called;
+ struct Handle
+ {
+ int entry;
+ void opAssign()(auto ref const(typeof(this)) that) const { called = true; }
+ }
+
+ const(Handle)[5] arr = [Handle(0), Handle(1), Handle(2), Handle(3), Handle(4)];
+ auto range = arr[].filter!(a => true)().takeExactly(3);
+
+ called = false;
+ range.front = Handle(42);
+ assert(called);
+}
+
/**
Returns a range with at most one element; for example, $(D
takeOne([42, 43, 44])) returns a range consisting of the integer $(D
@@ -4310,9 +4453,10 @@ if (isForwardRange!R && !isInfinite!R)
/// ditto
@property void front(ElementType!R val)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- _original[_index] = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ _original[_index] = __ctfe ? val : forward!val;
}
}
@@ -4422,9 +4566,10 @@ if (isForwardRange!R && !isInfinite!R)
/// ditto
@property auto front(ElementType!R val)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- return _current.front = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ return _current.front = __ctfe ? val : forward!val;
}
}
@@ -4767,6 +4912,35 @@ pure @safe unittest
assert(equal(r.save, "foof"));
}
+// https://issues.dlang.org/show_bug.cgi?id=24481
+@safe unittest
+{
+ import std.algorithm.iteration : filter;
+
+ bool called;
+ struct Handle
+ {
+ int entry;
+ void opAssign()(auto ref const(typeof(this)) that) const { called = true; }
+ }
+
+ const(Handle)[3] arr = [Handle(0), Handle(1), Handle(2)];
+ {
+ auto range = arr[].cycle().take(5);
+
+ called = false;
+ range.front = Handle(42);
+ assert(called);
+ }
+ {
+ auto range = arr[].filter!(a => true)().cycle().take(5);
+
+ called = false;
+ range.front = Handle(42);
+ assert(called);
+ }
+}
+
private alias lengthType(R) = typeof(R.init.length.init);
/**
@@ -7438,9 +7612,10 @@ struct FrontTransversal(Ror,
{
@property void front(ElementType val)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- _input.front.front = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ _input.front.front = __ctfe ? val : forward!val;
}
}
@@ -7497,9 +7672,10 @@ struct FrontTransversal(Ror,
{
@property void back(ElementType val)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- _input.back.front = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ _input.back.front = __ctfe ? val : forward!val;
}
}
}
@@ -7532,9 +7708,10 @@ struct FrontTransversal(Ror,
{
void opIndexAssign(ElementType val, size_t n)
{
- import std.algorithm.mutation : move;
+ import core.lifetime : forward;
- _input[n].front = move(val);
+ // __ctfe check is workaround for https://issues.dlang.org/show_bug.cgi?id=21542
+ _input[n].front = __ctfe ? val : forward!val;
}
}
mixin ImplementLength!_input;
@@ -7675,6 +7852,50 @@ pure @safe unittest
assert(ft.empty);
}
+// https://issues.dlang.org/show_bug.cgi?id=24481
+@safe unittest
+{
+ bool called;
+ struct Handle
+ {
+ int entry;
+ void opAssign()(auto ref const(typeof(this)) that) const { called = true; }
+ }
+
+ const(Handle)[][] arr = [[Handle(0), Handle(10)],
+ [Handle(1), Handle(11)],
+ [Handle(2), Handle(12)],
+ [Handle(3), Handle(13)],
+ [Handle(4), Handle(14)]];
+
+ {
+ auto range = arr.frontTransversal();
+
+ called = false;
+ range.front = Handle(42);
+ assert(called == true);
+
+ called = false;
+ range.back = Handle(42);
+ assert(called == true);
+ }
+ {
+ auto range = arr.frontTransversal!(TransverseOptions.assumeNotJagged)();
+
+ called = false;
+ range.front = Handle(42);
+ assert(called == true);
+
+ called = false;
+ range.back = Handle(42);
+ assert(called == true);
+
+ called = false;
+ range[0] = Handle(42);
+ assert(called == true);
+ }
+}
+
/**
Given a range of ranges, iterate transversally through the
`n`th element of each of the enclosed ranges. This function
@@ -10375,6 +10596,14 @@ private struct OnlyResult(T)
}
alias opDollar = length;
+ // FIXME Workaround for https://issues.dlang.org/show_bug.cgi?id=24415
+ import std.traits : hasElaborateCopyConstructor;
+ static if (hasElaborateCopyConstructor!T)
+ {
+ private static struct WorkaroundBugzilla24415 {}
+ public this()(WorkaroundBugzilla24415) {}
+ }
+
private this()(return scope auto ref T value)
{
ref @trusted unqual(ref T x){return cast() x;}