Bug 4279 – [AA] AAs change key type

Status
NEW
Severity
normal
Priority
P3
Component
druntime
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2010-06-06T04:54:52Z
Last change time
2024-12-07T13:31:01Z
Assigned to
Sean Kelly
Creator
bearophile_hugs
Moved to GitHub: dmd#17226 →

Comments

Comment #0 by bearophile_hugs — 2010-06-06T04:54:52Z
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).
Comment #1 by andrej.mitrovich — 2010-08-29T21:07:55Z
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.
Comment #2 by schveiguy — 2010-08-30T06:18:44Z
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.
Comment #3 by andrej.mitrovich — 2010-08-30T06:47:23Z
(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. :)
Comment #4 by schveiguy — 2010-08-30T06:57:47Z
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.
Comment #5 by hsteoh — 2012-02-27T17:34:23Z
const handling in AA's is badly broken; see bug 7512.
Comment #6 by robert.schadek — 2024-12-07T13:31:01Z
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