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.