On Monday, 2 April 2018 at 14:24:20 UTC, Nicholas Wilson wrote:
On Monday, 2 April 2018 at 14:07:21 UTC, Steven Schveighoffer wrote:
On 4/1/18 10:34 AM, ag0aep6g wrote:
[...]
I'm not so sure if that's fundamental. Can't we just say that the copy is head-mutable at the time when the postblit function is called, and it only becomes fully const after that?
[...]
Yes, precisely what I had been arguing here: https://issues.dlang.org/show_bug.cgi?id=18417#c5
[...]
Andrei did post an example where treating the designation as mutable, stuffing references to mutable data into is and then treating it as immutable leaves you with an immutable reference to immutable data.

This one?

----
int[] sneaky;
struct A
{
    private int[] innocent;
    this(this)
    {
        sneaky = innocent;
    }
}
void main()
{
    immutable a = A([1, 2, 3]);
    auto b = a;
    sneaky[1] = 42; // oops
    import std.stdio;
    writeln(a.innocent); // ooooops
}
----

That wouldn't be possible if `innocent` were only head-mutable in the postblit function, instead of fully mutable as it is currently (bug).

`innocent` would be typed as `immutable(int)[]`, and you could not assign it to the fully mutable `sneaky`.

However i think that loophole is fixed if you only allow assignment to const/immutable from a pure postblit.

Still must be head-mutable only. With fully mutable, you can mutate data that is seen as immutable elsewehre, even if the postblit function is pure:

----
struct S
{
    int* x;
    this(this) pure { *x = 13; }
}
void main()
{
    auto s = immutable S(new int(42));
    auto s2 = s;
    assert(*s.x == 42); /* fails; immutability has been broken */
}
----

Issue 18357 covers both Andrei's example, and this one.
https://issues.dlang.org/show_bug.cgi?id=18357

Reply via email to