Deprecating this(this)
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Sun Apr 1 17:08:37 UTC 2018
On 4/1/18 10:59 AM, Nicholas Wilson wrote:
> On Sunday, 1 April 2018 at 14:31:24 UTC, Andrei Alexandrescu wrote:
>> There's a mix of fundamental flaws and bugs. I'll get to the flaws in
>> a second. About the bugs: people have altered their code in various
>> ways to work with the bizarre semantics of this(this). Now, if we fix
>> various bugs in this(this) by virtually redefining it, then we'll
>> break a lot of code in a lot of ways. To wit, we fixed a small issue
>> and it already created problems:
>> https://github.com/dlang/dmd/pull/8032. That didn't contribute to the
>> decision but is quite illustrative.
>>
>> I found two fundamental flaws with this(this):
>>
>> 1. For immutable objects, typechecking in the presence of successive
>> modifications of data (first assignment by the compiler, then
>> modification by the user) is very difficult if not impossible. I don't
>> know how to do it. The single initialization model (raw/cooked) used
>> currently in regular immutable constructors works reasonably well and
>> is robust.
>>
>> 2. For shared objects, the part done by the compiler and the part done
>> by this(this) should be synchronized together. This makes it
>> impossible for the user to e.g. define a struct that gets copied
>> atomically.
>>
>
> See my other reply: but why is it necessary to consider the blit
> logically distinct from the postblit w.r.t to program flow observability?
>
> 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.
> 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.
>> There'd be an additional issue - this(this) is non-templated, which
>> requires combinatorial additions when qualifiers are present on the
>> source or destination side.
>
> (Perhaps this is what you're referring to, but all you have said so far
> is "this doesn't work and we need to fix it") the post blit is surely
> like a destructor: there's only one way to do it, irrespective of the
> attributes, especially of the intermediate is considered mutable until
> the end of post blit, like static module constructors initialising
> global immutables.
Negative. Ignoring qualifiers during copying opens holes in the type
system the size of China. Or at least Australia as it were :o). Consider:
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.
> I agree that we should fix any type checking bugs that may be present,
> and that we should strive to not make the same mistake twice, however I
> wouldn't call either of the above cases a showstopper. You will need to
> show more of what is broken and why it is broken given the expected
> breakage.
Such discussions will be indeed present in the DIP.
Andrei
More information about the Digitalmars-d
mailing list