On Mon, Feb 27, 2012 at 02:41:27PM -0800, H. S. Teoh wrote: > I'm investigating issue 7512, and narrowed down the problem to a bug > somewhere in the code that handles AA literals. [...]
OK, I've found the cause of the problem. Suppose you have an int array: const int[] key = [1,2,3,4]; and you create an AA out of it with an AA literal: int[int[]] map1 = [ key: 1234 ]; then internally, map1's key TypeInfo points to const(int)[]. However, if you do this: int[int[]] map2; map2[key] = 1234; then internally, map2's key TypeInfo points to int[]. (Non-const!) This difference means that the hash value of 'key' in map1 is *different* from the hash value of 'key' in map2. But if you now write this: map1[key] = 1234; for some reason, the hash value of 'key' is *still* computed using int[], even though map1's key TypeInfo points to const(int)[]. So the wrong hash value is computed, and the entry is not found. This means that you will never find anything in map1 using map1.get or map1[...]. But foreach works 'cos no hash values are involved. The above line will actually create a duplicate entry in the hash table, because 'key' is hashed to a different value than the one set by the AA literal. So the question is: 1) Why does map2's internal TypeInfo get set to int[] instead of const(int)[]? 2) Why does map1[key] use int[]'s version of getHash() even though map1's TypeInfo actually points to const(int)[]? This completely breaks AA literals for wstring keys, dstring keys, and in fact *any* array-typed key except for string (which for some blessed reason doesn't suffer from this breakage). Question: is this a compiler bug, or a druntime bug? T -- 2+2=4. 2*2=4. 2^2=4. Therefore, +, *, and ^ are the same operation.