mirror of
https://github.com/dlang/phobos.git
synced 2025-04-30 07:00:37 +03:00
Merge pull request #8736 from FeepingCreature/fix/issue-23844-immutable-chain
Fix issue 23844: Support ranges with immutable fields (like `only` with `immutable struct`) in `chain`.
This commit is contained in:
commit
cf97c75385
1 changed files with 40 additions and 11 deletions
|
@ -232,7 +232,7 @@ module std.range;
|
||||||
public import std.array;
|
public import std.array;
|
||||||
public import std.range.interfaces;
|
public import std.range.interfaces;
|
||||||
public import std.range.primitives;
|
public import std.range.primitives;
|
||||||
public import std.typecons : Flag, Yes, No;
|
public import std.typecons : Flag, Yes, No, Rebindable, rebindable;
|
||||||
|
|
||||||
import std.internal.attributes : betterC;
|
import std.internal.attributes : betterC;
|
||||||
import std.meta : aliasSeqOf, allSatisfy, anySatisfy, staticMap;
|
import std.meta : aliasSeqOf, allSatisfy, anySatisfy, staticMap;
|
||||||
|
@ -978,6 +978,11 @@ if (Ranges.length > 0 &&
|
||||||
static if (bidirectional) size_t backIndex;
|
static if (bidirectional) size_t backIndex;
|
||||||
else enum backIndex = source.length;
|
else enum backIndex = source.length;
|
||||||
|
|
||||||
|
this(typeof(this.tupleof) fields)
|
||||||
|
{
|
||||||
|
this.tupleof = fields;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
this(R input)
|
this(R input)
|
||||||
{
|
{
|
||||||
|
@ -1376,25 +1381,34 @@ if (Ranges.length > 0 &&
|
||||||
static if (allSatisfy!(hasLength, R) && allSatisfy!(hasSlicing, R))
|
static if (allSatisfy!(hasLength, R) && allSatisfy!(hasSlicing, R))
|
||||||
auto opSlice(size_t begin, size_t end) return scope
|
auto opSlice(size_t begin, size_t end) return scope
|
||||||
{
|
{
|
||||||
auto result = this;
|
// force staticMap type conversion to Rebindable
|
||||||
|
static struct ResultRanges
|
||||||
|
{
|
||||||
|
staticMap!(Rebindable, Ranges) fields;
|
||||||
|
}
|
||||||
|
auto sourceI(size_t i)() => rebindable(this.source[i]);
|
||||||
|
auto resultRanges = ResultRanges(staticMap!(sourceI, aliasSeqOf!(R.length.iota))).fields;
|
||||||
|
size_t resultFrontIndex = this.frontIndex;
|
||||||
|
static if (bidirectional)
|
||||||
|
size_t resultBackIndex = this.backIndex;
|
||||||
|
|
||||||
sw: switch (frontIndex)
|
sw: switch (frontIndex)
|
||||||
{
|
{
|
||||||
static foreach (i; 0 .. R.length)
|
static foreach (i; 0 .. R.length)
|
||||||
{
|
{
|
||||||
case i:
|
case i:
|
||||||
immutable len = result.source[i].length;
|
immutable len = resultRanges[i].length;
|
||||||
if (len <= begin)
|
if (len <= begin)
|
||||||
{
|
{
|
||||||
result.source[i] = result.source[i]
|
resultRanges[i] = resultRanges[i]
|
||||||
[len .. len];
|
[len .. len];
|
||||||
begin -= len;
|
begin -= len;
|
||||||
result.frontIndex++;
|
resultFrontIndex++;
|
||||||
goto case;
|
goto case;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.source[i] = result.source[i]
|
resultRanges[i] = resultRanges[i]
|
||||||
[begin .. len];
|
[begin .. len];
|
||||||
break sw;
|
break sw;
|
||||||
}
|
}
|
||||||
|
@ -1418,18 +1432,18 @@ if (Ranges.length > 0 &&
|
||||||
static foreach_reverse (i; 1 .. R.length + 1)
|
static foreach_reverse (i; 1 .. R.length + 1)
|
||||||
{
|
{
|
||||||
case i:
|
case i:
|
||||||
immutable len = result.source[i-1].length;
|
immutable len = resultRanges[i-1].length;
|
||||||
if (len <= cut)
|
if (len <= cut)
|
||||||
{
|
{
|
||||||
result.source[i-1] = result.source[i-1]
|
resultRanges[i-1] = resultRanges[i-1]
|
||||||
[0 .. 0];
|
[0 .. 0];
|
||||||
cut -= len;
|
cut -= len;
|
||||||
result.backIndex--;
|
resultBackIndex--;
|
||||||
goto case;
|
goto case;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.source[i-1] = result.source[i-1]
|
resultRanges[i-1] = resultRanges[i-1]
|
||||||
[0 .. len - cut];
|
[0 .. len - cut];
|
||||||
break sw2;
|
break sw2;
|
||||||
}
|
}
|
||||||
|
@ -1445,7 +1459,10 @@ if (Ranges.length > 0 &&
|
||||||
assert(0, "Internal library error. Please report it.");
|
assert(0, "Internal library error. Please report it.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
static if (bidirectional)
|
||||||
|
return Result(resultRanges, resultFrontIndex, resultBackIndex);
|
||||||
|
else
|
||||||
|
return Result(resultRanges, resultFrontIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result(rs);
|
return Result(rs);
|
||||||
|
@ -1643,6 +1660,18 @@ pure @safe unittest
|
||||||
assert(equal(r, "foobar"));
|
assert(equal(r, "foobar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://issues.dlang.org/show_bug.cgi?id=23844
|
||||||
|
pure @safe unittest
|
||||||
|
{
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
immutable int value;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto range = chain(only(S(5)), only(S(6)));
|
||||||
|
assert(range.array == [S(5), S(6)]);
|
||||||
|
}
|
||||||
|
|
||||||
pure @safe nothrow @nogc unittest
|
pure @safe nothrow @nogc unittest
|
||||||
{
|
{
|
||||||
// support non-copyable items
|
// support non-copyable items
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue