[SAoC 2021] Replace druntime Hooks with Templates: Milestone 4, Week 3
teodor.dutu at gmail.com
Fri Jan 7 20:23:46 UTC 2022
This week I finished converting `_d_newThrowable` to a template,
as well as its lowering in the compiler. The PRs for these are:
Also this week, I fixed the bug when compiling the new lowering
for `a ~= b` to either `_d_arrayappendcTX` or `_d_arrayappendT`.
It turned out it was because of how `$` is evaluated by the
compiler. The initial lowering when `b` was a single element
looked like this:
__ctfe ? a ~= b : _d_arrayappendcTX(a, 1), a[$ - 1] = b, a;
When a chain of concatenations (like `(a ~= b) ~= c`) was
lowered, in order for `(a ~= b)` to not be executed 3 times, I
saved the result in a temporary variable, before concatenating
`c` to it.
When this kind of expression was inlined, the `$` was mishandled
by the compiler, which resulted in an incorrect
`ArrayIndexError`. To solve this issue, I used `a.length` instead
of `$`. Now the lowering looks like this:
__ctfe ? a ~= b : _d_arrayappendcTX(a, 1), a[a.length - 1] = b, a;
// Note that the assignment above is actually a construction.
The PR that changes the lowering is:
A point of contention is the fact that I lower `a ~= b` to a
`CondExp`. As I explained
[here](https://github.com/dlang/dmd/pull/13495#discussion_r780274768), I believe this is the more elegant approach, despite being more complex.
Another issue was that because the current template
`_d_arrayappendcTX` uses a temporary implementation that calls
the old hook using a mixin.
For this reason, the new hook is always impure and has to be
declared `pure` so it can pass semantic analysis from `pure`
`_d_arrayappendT` also calls `_d_arrayappendcTX` and, hence, is
declared `pure` as well. However, `_d_arrayappendT` also calls
`copyEmplace`, which can sometimes be im`pure`. This causes an
error when trying to instantiate `_d_arrayappendT`. To bypass
this, I created an im`pure` private function in DRuntime, which
is called `_d_arrayappendT` after being made `pure` via a cast.
This way, `_d_arrayappendT` appears pure when it needs to be, but
is also able to call an impure `copyEmplace` when it has to.
The implementation of this hack is here:
Keep in mind that this is a hack for a stop-gap hook. In the
future, I intend to change the implementation of
`_d_arrayappendcTX` so that it won't call the old hook anymore
and thus allow attributes such as `pure`, `nothrow` etc to be
inferred by the compiler.
More information about the Digitalmars-d