[Issue 8556] Using take results in a corrupted call to opSlice
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Tue Oct 9 21:16:19 PDT 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8556
--- Comment #4 from Jonathan M Davis <jmdavisProg at gmx.com> 2012-10-09 20:52:16 PDT ---
Okay. Here's a test case which does not rely on either take, takeExactly or
hasSlicing (since they will likely be changed soon so that they don't have a
circular dependency, fixing the immediate problem in Phobos but not fixing the
compiler bug):
import std.algorithm;
import std.range;
import std.stdio;
import std.string;
import std.traits;
template isSliceable(R)
{
enum bool isSliceable = !isNarrowString!R && is(typeof(
(inout int _dummy=0)
{
R r = void;
auto s = r[1 .. 2];
static assert(isInputRange!(typeof(s)));
}));
}
struct Grab(Range)
if (isInputRange!(Unqual!Range)
&& !(isSliceable!(Unqual!Range) || is(Range T == Grab!T)))
{
private alias Unqual!Range R;
// User accessible in read and write
public R source;
private size_t _maxAvailable;
private enum bool byRef = is(typeof(&_input.front) == ElementType!(R)*);
alias R Source;
@property bool empty()
{
return _maxAvailable == 0 || source.empty;
}
@property auto ref front()
{
assert(!empty,
"Attempting to fetch the front of an empty "
~ Grab.stringof);
return source.front;
}
void popFront()
{
assert(!empty,
"Attempting to popFront() past the end of a "
~ Grab.stringof);
source.popFront();
--_maxAvailable;
}
static if (isForwardRange!R)
@property Grab save()
{
return Grab(source.save, _maxAvailable);
}
static if (isInfinite!R)
{
@property size_t length() const
{
return _maxAvailable;
}
alias length opDollar;
}
else static if (hasLength!R)
{
@property size_t length()
{
return min(_maxAvailable, source.length);
}
alias length opDollar;
}
}
Grab!R grab(R)(R input, size_t n)
if (isInputRange!(Unqual!R) && isSliceable!(Unqual!R))
{
static if (hasLength!R)
return input[0 .. min(n, input.length)];
else
return input[0 .. n];
}
Grab!(R) grab(R)(R input, size_t n)
if (is(R T == Grab!T))
{
return R(input.source, min(n, input._maxAvailable));
}
Grab!R grab(R)(R input, size_t n)
if (isInputRange!(Unqual!R) && !isSliceable!(Unqual!R) && !is(R T == Grab!T))
{
return Grab!R(input, n);
}
auto grabExactly(R)(R range, size_t n)
if (isInputRange!R && !isSliceable!R)
{
static if (is(typeof(grabExactly(range._input, n)) == R))
{
range._n = n;
return range;
}
else
{
static struct Result
{
R _input;
private size_t _n;
@property bool empty() const { return !_n; }
@property auto ref front()
{
assert(_n > 0, "front() on an empty " ~ Result.stringof);
return _input.front();
}
void popFront() { _input.popFront(); --_n; }
@property size_t length() const { return _n; }
alias length opDollar;
static if (isForwardRange!R)
@property auto save() { return this; }
}
return Result(range, n);
}
}
auto grabExactly(R)(R range, size_t n)
if (isSliceable!R)
{
return range[0 .. n];
}
struct Circle(Range)
if (isForwardRange!(Unqual!Range) && !isInfinite!(Unqual!Range))
{
alias Unqual!Range R;
R _original;
size_t _index;
this(R input, size_t index = 0) { _original = input; _index = index; }
@property auto ref front()
{
return _original[_index % _original.length];
}
enum bool empty = false;
void popFront() { ++_index; }
auto opSlice(size_t i, size_t j)
{
assert(j >= i, format("%s %s %s", i, j, _index));
writefln("%s %s %s", i, j, _index);
return grabExactly(typeof(this)(_original.save, _index + i), j - i);
}
}
Circle!R circle(R)(R input, size_t index = 0)
if (isRandomAccessRange!(Unqual!R) && !isInfinite!(Unqual!R))
{
return Circle!R(input, index);
}
void main()
{
uint[] arr = [1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U];
auto t = grab(circle(arr), 20);
auto cx = circle(arr);
auto slice = cx[23 .. 33];
assert(equal(slice, [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]), format("%s",
array(slice)));
}
It can probably be reduced further, but that already reduces it a fair bit.
It's been copied from Phobos with the names being tweaked (hasSlicing ->
isSliceable, take -> grab, takeExactly -> grabExactly) and some of the
unnecessary parts stripped out. So, this should provide a reproducible test
case even once hasSlicing and take have been fixed. I believe that the key
thing is the circular dependencies involved.
--
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
More information about the Digitalmars-d-bugs
mailing list