[Issue 1983] Delegates violate const
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri Jan 22 22:27:03 UTC 2021
https://issues.dlang.org/show_bug.cgi?id=1983
Bolpat <qs.il.paperinik at gmail.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |qs.il.paperinik at gmail.com
--- Comment #24 from Bolpat <qs.il.paperinik at 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.
--
More information about the Digitalmars-d-bugs
mailing list