the following code fails last assert:
int allocCount;
struct Repeat(T) {
alias Type = T;
Type value;
@property empty () const { return false; }
void popFront() {}
@property ref Type front() { return value; }
}
struct Take(Range) {
alias Type = Range.Type;
Range range;
size_t limit;
@property empty () const { return !limit; }
void popFront () { --limit; }
/*ref*/ Type front () { return range.front; }
}
auto repeat(Type) (auto ref Type t) { return Repeat!Type(t); }
auto take(Range) (auto ref Range range, size_t limit) { return Take!Range(range,limit); }
struct Test {
this (int id_) { ++allocCount; }
this (this) { ++allocCount; }
~this () { --allocCount; }
}
void testit () {
int count;
{
auto arr = Test(1).repeat().take(2);
foreach (ref v; arr) {
++count;
}
}
if (count == 0) assert(0);
assert(allocCount == 0);
}
void main () { testit(); }
if one will remove `ref` from loop, or uncomment `ref` in `.front()`, assertion pass.
Comment #1 by ketmar — 2016-08-08T01:24:09Z
Created attachment 1607
fix and test case
this patch fixes the issue by dropping `ref` from foreach args if `.front` is function, and it doesn't return by reference.
with trivial change this patch can also be used to resolve issue 11934.
Comment #2 by ketmar — 2016-08-10T20:13:13Z
Created attachment 1608
fix and test case, v2
remove `ref` only for types that needs dtor to be called. this *may* give some speedup when `.front` returns structs without dtors.
Comment #3 by razvan.nitu1305 — 2023-05-30T15:01:57Z
This seems to have been fixed. Using latest master I was able to compile the code and run it successfully.