I've just learned that the following is apparently valid code (in the context of analyzing a reported LDC issue, https://github.com/ldc-developers/ldc/issues/2537):
void main() @safe
{
typeof(null) nul;
void* ptr;
int[string] aa = [ "one": 123 ];
static assert(!__traits(compiles, ptr + ptr));
auto sum = nul + nul;
auto diff = nul - nul;
static assert(!__traits(compiles, aa + aa));
static assert(!__traits(compiles, aa + ptr));
static assert(!__traits(compiles, ptr + aa));
assert(aa + nul == aa);
assert(nul + aa == aa);
static assert(!__traits(compiles, aa - aa));
static assert(!__traits(compiles, aa - ptr));
static assert(!__traits(compiles, ptr - aa));
assert(aa - nul == aa);
assert(nul - aa == aa);
}
Firstly, these weird binop expressions make it into the AST, so the backend needs to handle stuff like that.
If `nul + nul` etc. is really supposed to be valid, the front-end could rewrite the binop as CommaExp `lhs, rhs, typeof(null).init`.
And while `aa + aa` is invalid, `aa + nul` makes it into the AST as `aa + cast(int[string]) nul`, so that the backend needs to handle additions and subtractions of associative arrays (semantics?! :D).
Secondly, the last assert leads to a segfault in this @safe code during AA comparison, as `nul - aa` yields (a pointer to) an invalid AA, so DMD appears to have chosen pointer subtraction as semantics for AA subtraction.
Comment #1 by robert.schadek — 2024-12-13T18:56:26Z