Lowerings to strongly pure _d_arrayctor trigger warnings or risk being incorrectly removed

Paul Backus snarwin at gmail.com
Tue Oct 12 20:07:32 UTC 2021


On Tuesday, 12 October 2021 at 19:31:34 UTC, Teodor Dutu wrote:
> On Tuesday, 12 October 2021 at 18:27:53 UTC, Paul Backus wrote:
>> On Tuesday, 12 October 2021 at 18:04:21 UTC, Teodor Dutu wrote:
>>>
>>> I have read the documentation at the links you left, but I 
>>> can't see why the usage of `_d_arrayctor` would be an 
>>> undefined behaviour.
>>
>> `_d_arrayctor` casts away `immutable` internally--either 
>> [here][1], directly, or [here][2] indirectly via `copyEmplace` 
>> (which casts it away [here][3]). It then uses `memcpy` to 
>> mutate the memory that was originally typed as `immutable`. 
>> This is undefined behavior, according to the language spec.
>>
>> [1]: 
>> https://github.com/dlang/druntime/blob/16c836a7b084b935504427579e2d646c462ee6e4/src/core/internal/array/construction.d#L77
>> [2]: 
>> https://github.com/dlang/druntime/blob/16c836a7b084b935504427579e2d646c462ee6e4/src/core/internal/array/construction.d#L59
>> [3]: 
>> https://github.com/dlang/druntime/blob/16c836a7b084b935504427579e2d646c462ee6e4/src/core/lifetime.d#L1239
>>
>>> This lowering only occurs when initialising static arrays or 
>>> slices
>>
>> The spec does not currently make an exception for initializing 
>> static arrays or slices, so the fact that it only occurs in 
>> that context does not make any difference to whether the spec 
>> considers it UB.
>
> I see your point now. But this behaviour is not new. The 
> current implementation uses [this 
> hook](https://github.com/dlang/druntime/blob/a17bb23b418405e1ce8e4a317651039758013f39/src/rt/arrayassign.d#L170), which suffers from the same shortcomings. Furthermore, the hook uses `TypeInfo`, which makes it slower than what I'm trying to achieve with the templated approach.
>
> And secondly, bear in mind that the lowering only occurs when 
> the `lhs` is being constructed, which means that two things can 
> happen:
> - the compiler can perform constant propagation by replacing 
> the `rhs` variable with an array literal, which will **not** be 
> lowered to `_d_arrayctor`: 
> https://github.com/dlang/dmd/blob/3aa786cfb6990ff5f9c5085d0efd3421c3adc956/src/dmd/expressionsem.d#L9778
> - the compiler doesn't perform this optimisation, which means 
> that some data has to be written into the `const`/`immutable` 
> array (`lhs`).
>
> I don't see how the second scenario can be avoided, with or 
> without `_d_arrayctor`.

Yes, I understand that the compiler has to initialize the array 
somehow, and that in the general case this requires writing to 
memory typed as `immutable`.

My point is not that `_d_arrayctor` should not do its job, but 
that the current language spec makes it impossible to implement 
`_d_arrayctor` in D (as opposed to "in compiler magic") without 
invoking UB.

This means that if you want to implement `_d_arrayctor` in D, you 
will have to start by changing the language spec.

If you don't, any workaround you come up with is still going to 
involve UB, which means it will be at risk of falling apart as 
soon as it is exposed to a more powerful optimizer.


More information about the Digitalmars-d mailing list