February 04, 2019
https://issues.dlang.org/show_bug.cgi?id=19647

          Issue ID: 19647
           Summary: std.range.takeOne opSlice incorrect for empty slice of
                    non-forward input range
           Product: D
           Version: D2
          Hardware: x86
                OS: Mac OS X
            Status: NEW
          Severity: normal
          Priority: P1
         Component: phobos
          Assignee: nobody@puremagic.com
          Reporter: jrdemail2000-dlang@yahoo.com

std.range.takeOne supports slicing. The slice [0..0] should return an empty range. However, when takeOne is used on a non-forward input range, the range returned by [0..0] is non-empty.

A PR is in progress.

--- Test program (test2.d) ---

import std.range;
import std.stdio;

struct ValInputRange(R)
{
    R data;
    this(R _data) pure @safe nothrow { data = _data; }
    @property bool empty() pure @safe nothrow { return data.empty; }
    @property auto front() pure @safe nothrow { assert(!empty); return
data.front; }
    void popFront() pure @safe nothrow { assert(!empty); data.popFront(); }
}

auto valInputRange(R)(R range) { return ValInputRange!R(range); }

void main(string[] args)
{
    auto a = [1, 2, 3, 4, 5];
    auto r1 = a.takeOne;

    auto q1 = r1[0..0];
    writeln("q1.length: ", q1.length, "; q1.empty: ", q1.empty);

    auto r2 = a.valInputRange.takeOne;
    auto q2 = r2[0..0];
    writeln("q2.length: ", q2.length, "; q2.empty: ", q2.empty);
}
------------------------------------

Run:

$ dmd --version
DMD64 D Compiler v2.084.0

$ dmd test2.d

$ ./test2
q1.length: 0; q1.empty: true
q2.length: 1; q2.empty: false

The bug is that q2 should have length==0 and empty==true, same as q1.

--