dmd
dmd copied to clipboard
Associative array `byKey` and `byKeyValue` allow writing keys
Using aa.byKey one can write the keys of an associative array and break its invariants. It even works when the AA is typed immutable:
void main() @safe
{
int[int] aa = [1: 10];
foreach (ref k; aa.byKey)
{
pragma(msg, typeof(k)); // int, but should be const(int) ❌
k = 2; // should be an error (assignment to const) ❌
}
// `aa` is broken now
assert(aa[1] == 10); // fails ❗
assert(aa[2] == 10); // fails ❗
}
Problems with immutable associative arrays:
void main() @safe
{
immutable int[int] aa = [1: 10];
foreach (ref k; aa.byKey)
{
pragma(msg, typeof(k)); // int, but should be immutable(int) ❌
k = 2; // should be an error (assignment to immutable) ❌
}
// For completeness, `byValue` works as expected:
foreach (ref v; aa.byValue)
{
pragma(msg, typeof(v)); // immutable(int) ✔️
v = 20; // Error: cannot modify `immutable` expression ✔️
}
}
The same applies to byKeyValue:
void main() @safe
{
int[int] aa = [1: 10];
foreach (kv; aa.byKeyValue)
{
pragma(msg, typeof(kv.key)); // int, but should be const(int) ❌
kv.key = 2; // should be an error (assignment to const) ❌
}
}
and
void main() @safe
{
immutable int[int] aa = [1: 10];
foreach (kv; aa.byKeyValue)
{
pragma(msg, typeof(kv.key)); // int, but should be immutable(int) ❌
kv.key = 2; // should be an error (assignment to immutable) ❌
}
}
Seems to be a duplicate of #17408, though this is interesting as it points out immutable violation too.
Note: if this gets fixed, the AA properties docs (updated in dlang/dlang.org#4339) need to have the 2 bug notes removed.