On Sunday, 1 April 2018 at 17:08:37 UTC, Andrei Alexandrescu wrote:
On 4/1/18 10:59 AM, Nicholas Wilson wrote:
for 1. consider
immutable foo = ...;
immutable bar = foo;
to be
immutable foo = ...;
immutable bar = () {mutable _ = bitcopy(foo); _.__postblit(); return _;}();

Negative. The problem is typechecking postblit itself, not its invocation.

Nit sure that I follow but, see comment below on your immutable example.

for 2. you would have to synchronize anyway for shared, it makes no difference.

Negative. Consider:

shared struct Point
{
    private long x, y, z;
    private Mutex mutex;
    ...
}

Task: define the copy primitive of Point so atomically copy x, y, and z using mutex. The problem is, the compiler will memcpy the three longs non-atomically before the user even gets a crack at intercepting the operation.


What I meant was:
Point p = ...;
auto pp = p; // bit copy + postblit = WRONG
Point pp;
synchronized (p.mutex) { pp = p; } // synchronised: bitcopy is inseparable from the postblit

Perhaps there is a way to make that automatic / nicer to use?

[...]
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
}

Sadly this (and many similar ones) compiles and runs warning-free on today's compiler. We really need to close this loop, like, five years ago.

How much of this class of bug would be eliminated by requiring that `this(this)` be pure for assignment to const and immutable objects? Arguably this(this) should always be pure in any sane program. The only reason I can think of is if you're trying to perf the number of copies you're making, but there is compiler help for that.


Reply via email to