With DMD v2.046 this program prints const(char)[] instead of char[] import std.stdio: writeln; void main() { int[char[]] data = [cast(char[])"foo" : 1]; foreach (key, val; data) writeln(typeid(typeof(key))); } Modifying AA keys after they are inserted in the AA is indeed bad because their hash value and position inside the AA doesn't get recomputed. But the current design/behaviour is surprising and bad, because I have asked for a key type and the runtime/compiler gives me a different key type (forcing me to use casts). There are two possible behaviours that I see acceptable here: 1) to disallow AAs with mutable keys, their literals and definition too (as Python does), so in this case this variable definition becomes a compile-time error: int[int[]] data; 2) or to allow mutable keys (and hope the programmer will not mutate them) (as I think D1 does), and keep their type unchanged (mutable).
As of 2.048, and according to my tests, DMD forces AA's to have a const type as the key type. For example: import std.stdio: writeln; void main() { int[int[]] data; writeln(typeid(data)); } Prints: int[const(int)[]] And your AA literal key type gets converted to a const type as well: import std.stdio: writeln; void main() { writeln(typeid([cast(char[])"foo" : 1])); } Prints: int[const(char)[]] What happens here (if my interpretation is right), is that foo is first an array of immutable chars, it's casted to a mutable array of chars, and then DMD sees it is a key of an AA literal so it converts it to an array of const chars. So DMD is most probably doing this: On the left of assignment: int[char[]] data -> int[const(char)[]] data On the right of assignment: [cast(char[])const(char)[] : int] -> int[cast(char[])const(char)[]] -> int[char[]] -> int[const(char)[]] And the whole thing becomes: int[const(char)[]] data = int[const(char)[]] So if I got that right then DMD automatically changes the key type of an AA to be const, regardless of any casts. Having to change int[] to const(int)[] directly in the code would probably make the AA's harder to read, so maybe that's a good thing.
I think changing the key type to const during iteration is a useless gesture, and just serves as an annoyance rather than a guarantee. See bug 4410 that I reported later but for a different reason.
(In reply to comment #2) > I think changing the key type to const during iteration is a useless gesture, > and just serves as an annoyance rather than a guarantee. > > See bug 4410 that I reported later but for a different reason. In this case it doesn't change the key type during iteration, it changes it in the declaration: import std.stdio: writeln; void main() { int[char[]] data = [cast(char[])"foo" : 1]; writeln(typeid(data)); } Prints: int[const(char)[]] Unless I got it wrong here. :)
Oh, I didn't notice that. I was looking at bearophile's code. But my point is the same -- converting to const does not guarantee anything. In reality, the only place where you are affected is during iteration, as everywhere else, the key is an input.
const handling in AA's is badly broken; see bug 7512.
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17226 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB