DIP 1025--Dynamic Arrays Only Shrink, Never Grow--Community Review Round 1
John Colvin
john.loughran.colvin at gmail.com
Tue Nov 12 15:54:22 UTC 2019
On Monday, 11 November 2019 at 10:27:26 UTC, Mike Parker wrote:
> This is the feedback thread for the first round of Community
> Review for DIP 1025, "Dynamic Arrays Only Shrink, Never Grow":
>
> https://github.com/dlang/DIPs/blob/1b525ec4c914c06bc286c1a6dc93bf1533ee56e4/DIPs/DIP1025.md
See here for my response:
https://gist.github.com/John-Colvin/c9c0b79bc9d47ed8d57ec9e959d0542b
Included below for convenience and record:
The DIP provides 2 examples to justify itself:
1) unpredictable mutable aliasing after appends
2) 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.
### Let's consider the first example:
```D
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 `~=`.*
### On to the second example:
```D
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.
## Conclusion:
Overall, this change 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.*
More information about the Digitalmars-d
mailing list