[Issue 22092] [REG2.067] for loop over range with closure loops infinitely
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu Jul 1 01:25:30 UTC 2021
https://issues.dlang.org/show_bug.cgi?id=22092
Mathias LANG <pro.mathias.lang at gmail.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |pro.mathias.lang at gmail.com
--- Comment #1 from Mathias LANG <pro.mathias.lang at gmail.com> ---
> 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);
}
```
--
More information about the Digitalmars-d-bugs
mailing list