[Issue 16056] immutable delegate can mutate through context pointer
https://issues.dlang.org/show_bug.cgi?id=16056 Sobirari Muhomorichanged: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |DUPLICATE --- Comment #7 from Sobirari Muhomori --- *** This issue has been marked as a duplicate of issue 1983 *** --
[Issue 16056] immutable delegate can mutate through context pointer
https://issues.dlang.org/show_bug.cgi?id=16056 --- Comment #6 from Eyal Lotem--- (In reply to ag0aep6g from comment #5) > (In reply to Eyal Lotem from comment #4) > > immutable void delegate() pure > > > > vs. > > > > immutable void delegate() immutable pure > > When the delegate is part of an immutable struct instance, it has the former > type, too: > > > struct S { void delegate() pure f; } > immutable s = S(); > pragma(msg, typeof(s.f)); /* immutable(void delegate() pure) */ > > > I suppose your point is that it should be the latter type, with two > "immutable"s. > > Fair enough, but I don't think that distinction is worth having. D doesn't > have head const with pointers. Why should we make delegates a special case? > > So in my opinion, `immutable void delegate()` should imply an immutable > context pointer, making it the same type as `immutable void delegate() > immutable`. Just like `immutable(int*)` is the same as > `immutable(immutable(int)*)`. > > The compiler agrees (to some extent): > > > alias A = immutable int* delegate(); > alias B = immutable int* delegate() immutable; > static assert(is(A == B)); /* passes */ > > > But then there's this: > > > void main() > { > int x = 1; > const void delegate() dg1 = { ++x; }; > const void delegate() const dg2 = { ++x; }; > } > > > That compiles, but when you take the dg1 line away, then the dg2 line isn't > accepted anymore. And when you swap them around, both lines are rejected. > There's obviously something wrong here. I've filed a separate issue: > https://issues.dlang.org/show_bug.cgi?id=16058 I agree `immutable delegate ..` should imply the context is immutable too (i.e: no head-const ptrs). But possibly not the other way around. It makes sense to have a mutable delegate with an immutable context (like a mutable ptr to immutable data). --
[Issue 16056] immutable delegate can mutate through context pointer
https://issues.dlang.org/show_bug.cgi?id=16056 --- Comment #5 from ag0ae...@gmail.com --- (In reply to Eyal Lotem from comment #4) > immutable void delegate() pure > > vs. > > immutable void delegate() immutable pure When the delegate is part of an immutable struct instance, it has the former type, too: struct S { void delegate() pure f; } immutable s = S(); pragma(msg, typeof(s.f)); /* immutable(void delegate() pure) */ I suppose your point is that it should be the latter type, with two "immutable"s. Fair enough, but I don't think that distinction is worth having. D doesn't have head const with pointers. Why should we make delegates a special case? So in my opinion, `immutable void delegate()` should imply an immutable context pointer, making it the same type as `immutable void delegate() immutable`. Just like `immutable(int*)` is the same as `immutable(immutable(int)*)`. The compiler agrees (to some extent): alias A = immutable int* delegate(); alias B = immutable int* delegate() immutable; static assert(is(A == B)); /* passes */ But then there's this: void main() { int x = 1; const void delegate() dg1 = { ++x; }; const void delegate() const dg2 = { ++x; }; } That compiles, but when you take the dg1 line away, then the dg2 line isn't accepted anymore. And when you swap them around, both lines are rejected. There's obviously something wrong here. I've filed a separate issue: https://issues.dlang.org/show_bug.cgi?id=16058 --
[Issue 16056] immutable delegate can mutate through context pointer
https://issues.dlang.org/show_bug.cgi?id=16056 --- Comment #4 from Eyal Lotem--- immutable void delegate() pure(In reply to ag0aep6g from comment #3) > (In reply to Eyal Lotem from comment #2) > > This is simpler -- but this simpler example isn't a bug: a pure func that > > takes a mutable delegate is "weakly pure" because it doesn't take an > > immutable argument. You could say that the simplified pure func takes an > > explicitly mutable argument, so it is known to be weakly pure. > > pure_func's parameter isn't mutable. It's explicitly marked immutable. immutable void delegate() pure vs. immutable void delegate() immutable pure Arguably, you can claim that if you've chosen the former form, you knowingly forfeited mutability for the delegate. However, once the delegate is wrapped in a struct, you would expect that transitivity would take care of full immutability. --
[Issue 16056] immutable delegate can mutate through context pointer
https://issues.dlang.org/show_bug.cgi?id=16056 --- Comment #3 from ag0ae...@gmail.com --- (In reply to Eyal Lotem from comment #2) > This is simpler -- but this simpler example isn't a bug: a pure func that > takes a mutable delegate is "weakly pure" because it doesn't take an > immutable argument. You could say that the simplified pure func takes an > explicitly mutable argument, so it is known to be weakly pure. pure_func's parameter isn't mutable. It's explicitly marked immutable. --
[Issue 16056] immutable delegate can mutate through context pointer
https://issues.dlang.org/show_bug.cgi?id=16056 --- Comment #2 from Eyal Lotem--- (In reply to ag0aep6g from comment #1) > The struct doesn't really matter here, as far as I see. Simplified code: > > > import std.stdio; > > pure void pure_func(immutable void delegate() pure f) > { > f(); > } > > void main() { > int y; > writeln("Before: ", y); > pure_func({ y++; }); > writeln("After: ", y); > } > > > Possibly a duplicate of issue 11043 or issue 1983. This is simpler -- but this simpler example isn't a bug: a pure func that takes a mutable delegate is "weakly pure" because it doesn't take an immutable argument. You could say that the simplified pure func takes an explicitly mutable argument, so it is known to be weakly pure. When you do take an immutable argument in a pure function -- the immutability is supposed to be transitive -- so it is supposed to be strongly pure. --
[Issue 16056] immutable delegate can mutate through context pointer
https://issues.dlang.org/show_bug.cgi?id=16056 ag0ae...@gmail.com changed: What|Removed |Added Keywords||accepts-invalid CC||ag0ae...@gmail.com Component|dlang.org |dmd Summary|[The D Bug Tracker] |immutable delegate can ||mutate through context ||pointer Severity|enhancement |normal --- Comment #1 from ag0ae...@gmail.com --- The struct doesn't really matter here, as far as I see. Simplified code: import std.stdio; pure void pure_func(immutable void delegate() pure f) { f(); } void main() { int y; writeln("Before: ", y); pure_func({ y++; }); writeln("After: ", y); } Possibly a duplicate of issue 11043 or issue 1983. --