The DIP provides 2 examples to justify itself:
-
unpredictable mutable aliasing after appends
-
unpredictable changes of ownership caused by appends
They can share the same cause (~=
), but are two distinct symptoms, and can also have other causes. They have a unifying aspect which is unpredictable aliasing.
The breakage of the DIP is immense, so there needs to be a commensurately large upside and no reasonable alternative path with less breakage.
int[] slice = cast(int*)malloc(10 * int.sizeof)[0 .. 10];
slice ~= 1;
free(slice.ptr); // Oops!
free
is not an @safe
operation and requires some conditions to be met for correct use. These conditions are as follows:
free
happens after all accesses to the allocation referenced by the passed pointer.- the allocation referenced by the passed pointer was made by
{m,c,re}alloc
as such, you can't really ever call free
without completely trusting the path by which the data travelled, from inception ({m,c,re}alloc
) to the call to free
. This may be achieved by a variety of ways (e.g. a MallocSlice
type that encapsulates the slice, or by having the path be very short and doing it manually) but fundamentally if I write a function taking a slice and then freeing the pointer, I cannot mark it as @trusted
, regardless of whether ~=
is allowed or not.
That ~=
will cause a new array to be allocated unpredictably is not the problem, the problem is that it can happen at all. If we look at it probabilistically: the problem is not that the probability of re-allocation is in (0, 1)
, the problem is that it's not 0
. Someone can write slice = slice ~ 1
and get the same behaviour, so my considerations when calling free
have not changed by disallowing ~=
.
enum { dead, alive }
int[] cat = new int[6];
cat[5] = alive;
int[] b = cat;
b ~= 1; // may or may not move b to new location
b[5] = dead; // indeterminate whether cat[5] is dead or alive
This is a sticky one. ~=
applied to data where there are >1 references and >0 are mutable is liable to cause problems of unpredictable action at a distance. Removing ~=
makes it slightly harder to do this, but seeing as it's so very easy to do the same thing in other ways (a = b ? a : (a ~ 2)
and many other trivial examples) it arguably doesn't matter much. I could believe it makes it less likely to do by accident.
Overall, this DIP seems to not buy anyone much, but costs a lot. It correctly identifies a problem (or 2 problems, depending how you look at it), but the proposed solution does not appear on a simple reading to solve the problem.
The DIP does not provide any examples of what is directly enabled by the change and I was not able to infer it from the current text.
The author should explain what previously impossible/unsafe code can now be made possible/safe given the proposed change.