[Issue 16374] New: Foreach lowering tries opSlice before range primitives

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Wed Aug 10 14:11:58 PDT 2016


https://issues.dlang.org/show_bug.cgi?id=16374

          Issue ID: 16374
           Summary: Foreach lowering tries opSlice before range primitives
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody at puremagic.com
          Reporter: lodovico at giaretart.net
                CC: lodovico at giaretart.net

When lowering a foreach, the compiler gives priority to opSlice over
front/popFront/empty, which is counter-intuitive (and also undocumented).

The following code, taken from [1] shows the issue: the overridden front in
RangeWrapper is ignored when the wrapped range also defines opSlice, which is
true for RangeT (the range returned by Array.opSlice). This causes the foreach
output to be different from the expected old-style for loop equivalent.

Example code:
=====================================================
import std.stdio, std.container.array;
struct RangeWrapper(Range)
{
    Range range;
    alias range this;

    auto front()
    {
        return range.front + 1;
    }
}
auto rangeWrapper(Range)(auto ref Range range)
{
    return RangeWrapper!Range(range);
}
void main()
{
    Array!int array;
    array.insertBack(3);

    foreach (i; rangeWrapper(array[]))
        writeln(i);           // prints 3, which is wrong

    // isn't the above foreach equivalent to the following loop ?

    for (auto r = rangeWrapper(array[]); !r.empty; r.popFront())
        writeln(r.front);     // correctly prints 4
}
=====================================================

[1] http://forum.dlang.org/thread/fzwofczyvkxgmtvncmxb@forum.dlang.org

--


More information about the Digitalmars-d-bugs mailing list