https://issues.dlang.org/show_bug.cgi?id=22092
Mathias LANG <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected] --- Comment #1 from Mathias LANG <[email protected]> --- > 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); } ``` --
