Skip to content

Commit

Permalink
Fix issues 19644, 19647 - std.range.takeOne.opSlice bugs (#6853)
Browse files Browse the repository at this point in the history
Fix issues 19644, 19647 - std.range.takeOne.opSlice bugs
merged-on-behalf-of: Nathan Sashihara <n8sh@users.noreply.github.com>
  • Loading branch information
jondegenhardt authored and dlang-bot committed Feb 8, 2019
1 parent e10d6a7 commit 9f545db
Showing 1 changed file with 91 additions and 2 deletions.
93 changes: 91 additions & 2 deletions std/range/package.d
Expand Up @@ -2655,8 +2655,15 @@ if (isInputRange!R)
}
auto opSlice(size_t m, size_t n)
{
assert(m <= n && n < length, "Attempting to index a takeOne out of bounds");
return n > m ? this : Result(_source, false);
assert(
m <= n,
"Attempting to slice a takeOne range with a larger first argument than the second."
);
assert(
n <= length,
"Attempting to slice using an out of bounds index on a takeOne range."
);
return n > m ? this : Result(_source, true);
}
// Non-standard property
@property R source() { return _source; }
Expand Down Expand Up @@ -2695,7 +2702,89 @@ pure @safe nothrow @nogc unittest
static assert(!isForwardRange!NonForwardRange);

auto s = takeOne(NonForwardRange());
assert(s.length == 1);
assert(!s.empty);
assert(s.front == 42);
assert(s.back == 42);
assert(s[0] == 42);

auto t = s[0 .. 0];
assert(t.empty);
assert(t.length == 0);

auto u = s[1 .. 1];
assert(u.empty);
assert(u.length == 0);

auto v = s[0 .. 1];
s.popFront();
assert(s.length == 0);
assert(s.empty);
assert(!v.empty);
assert(v.front == 42);
v.popBack();
assert(v.empty);
assert(v.length == 0);
}

pure @safe nothrow @nogc unittest
{
struct NonSlicingForwardRange
{
enum empty = false;
int front() { return 42; }
void popFront() {}
@property auto save() { return this; }
}

static assert(isForwardRange!NonSlicingForwardRange);
static assert(!hasSlicing!NonSlicingForwardRange);

auto s = takeOne(NonSlicingForwardRange());
assert(s.length == 1);
assert(!s.empty);
assert(s.front == 42);
assert(s.back == 42);
assert(s[0] == 42);
auto t = s.save;
s.popFront();
assert(s.length == 0);
assert(s.empty);
assert(!t.empty);
assert(t.front == 42);
t.popBack();
assert(t.empty);
assert(t.length == 0);
}

// Test that asserts trigger correctly
@system unittest
{
import std.exception : assertThrown;
import core.exception : AssertError;

struct NonForwardRange
{
enum empty = false;
int front() { return 42; }
void popFront() {}
}

auto s = takeOne(NonForwardRange());

assertThrown!AssertError(s[1]);
assertThrown!AssertError(s[0 .. 2]);

size_t one = 1; // Avoid style warnings triggered by literals
size_t zero = 0;
assertThrown!AssertError(s[one .. zero]);

s.popFront;
assert(s.empty);
assertThrown!AssertError(s.front);
assertThrown!AssertError(s.back);
assertThrown!AssertError(s.popFront);
assertThrown!AssertError(s.popBack);
}

//guards against issue 16999
Expand Down

0 comments on commit 9f545db

Please sign in to comment.