https://issues.dlang.org/show_bug.cgi?id=1983
Bolpat <qs.il.paperi...@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |qs.il.paperi...@gmail.com --- Comment #24 from Bolpat <qs.il.paperi...@gmail.com> --- (In reply to anonymous4 from comment #21) > Nice progress. New test case: > --- > struct A > { > void delegate() a; > int b; > void f(){ a=&g; } > void g(){ b++; } > int h() const { a(); return b; } > } > > void f(ref const A a) > { > const int b1=a.h, b2=a.h; > assert(b1==b2,"changed"); > } > > unittest > { > A a; > a.f(); > f(a); > } > --- I fail to see how this is a problem. Const correctness isn't as strong as you think it is. You're conflating const and immutable in a non-obvious way. First, consider that the unittest's variable `a` is mutable, so (this is important!) the free function `f` cannot expect its parameter `a` not to change when doing anything. One usually thinks that aliasing is necessary for that (and even here, aliasing occurs, its just rather hidden), but because `f` only takes one `const` parameter and is factually pure (annotate all functions and the unittest `pure` if you like, it compiles, I tried). What you do by calling `a.f()` in the unittest, is creating a mutable reference to `a` in the context pointer of `A.a` (why TF did you have to use names multiple times??). In the const method `h`, the delegate `a` is const which means you cannot assign it like in `A.f`, but calling it is okay. This way, using its mutable context pointer, it mutates the underlying object. While it looks like a `const` method mutates the object, this isn't a const violation. One could argue that the context pointer in a delegate is part of it. Viewing a delegate as a pair (void function(ref Context, ...) fp, Context* ptr) where Context is a suitable struct holding the contents of the context, ptr is transitively part of the struct and in a const method, must be const. If this were an issue of const only, but not immutable, this bug report would be invalid. HOWEVER, this can be rephrased in a completely pure/immutable style. Immutable means much more than const. It is much easier to spot violations of it, since any change is one. I made a version of the quoted code that clearly violates immutable: struct A { void delegate() pure dg; int value; this(int value) pure { this.value = value; this.dg = &this.mut; } void mut() pure { ++value; } int kaboom() pure const { dg(); return value; } } void f(ref const A x) pure { immutable int v1 = x.kaboom; immutable int v2 = x.kaboom; assert(v1 == v2, "changed"); // fails } void main() pure { immutable A a = immutable(A)(0); f(a); // usually fails, but might pass due to optimization: assert(a.value == 0, "changed"); } It's even hard to pin-point which exact part of the code should be an error. --