Issue 16374 - Foreach lowering tries opSlice before range primitives
Summary: Foreach lowering tries opSlice before range primitives
Status: RESOLVED DUPLICATE of issue 14619
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-08-10 21:11 UTC by Lodovico Giaretta
Modified: 2016-08-11 12:49 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Lodovico Giaretta 2016-08-10 21:11:58 UTC
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
Comment 1 Steven Schveighoffer 2016-08-11 12:49:04 UTC
I actually think this is a duplicate of the other issue. Basically the same problem, just different reasons why we shouldn't do it :)

*** This issue has been marked as a duplicate of issue 14619 ***