Comment #0 by dlang-bugzilla — 2021-06-29T19:38:22Z
///////////////////// test.d /////////////////////
void formatRange(T)(T val)
{
for (size_t i; !val.empty; val.popFront, i) {}
}
void fun() {}
auto makeRange()()
{
int pos;
struct R
{
bool empty() { return pos == 3; }
void popFront() const
{
++pos;
version (no_bug) fun();
}
}
return R();
}
void main()
{
auto r = makeRange;
formatRange(r);
}
//////////////////////////////////////////////////
Note that with -version=no_bug (i.e. adding a call to an empty function), the bug does not manifest.
Introduced in https://github.com/dlang/dmd/pull/3956
Comment #1 by pro.mathias.lang — 2021-07-01T01:25:30Z
> Note that with -version=no_bug (i.e. adding a call to an empty function), the bug does not manifest.
Looking at the PR that introduced the regression, I think that is because it prevents the compiler from inferring "pure" on `popFront`.
Currently `popFront` compiles to:
```
% nm bug.o| ddemangle | grep popFront
00000000000001d0 S const pure nothrow @nogc @safe void bug.makeRange!().makeRange().R.popFront()
0000000000000130 S _bug.makeRange!().makeRange.R.popFront.eh
```
But it is *not* `const pure`, because it obviously modify its context!
Brainstorming, I think that, to solve this, we could:
1) Reject `const`: Consider that `const` applies to the captured context as well.
This is good old https://issues.dlang.org/show_bug.cgi?id=1983
2) Do not infer `pure`: Consider that the context as inherently non-pure.
I don't think that's the right thing to do, however, the context should be
non-pure if the function from which the context is taken isn't pure.
Currently you can bypass `pure` by taking a pointer to a global,
and accessing that pointer from `popFront`:
```D
void formatRange(T)(T val)
{
for (size_t i; !val.empty; val.popFront, i) {}
}
int pos; // This changed
auto makeRange()()
{
int* p = &pos; // This changed
struct R
{
bool empty() { return pos == 3; }
void popFront() const
{
++(*p); // This changed
}
}
return R();
}
void main()
{
auto r = makeRange;
formatRange(r);
}
```
Comment #2 by robert.schadek — 2024-12-13T19:17:28Z