www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 7512] New: Associative arrays with dstring as key do not work correctly

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512

           Summary: Associative arrays with dstring as key do not work
                    correctly
           Product: D
           Version: D2
          Platform: All
        OS/Version: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: druntime
        AssignedTo: nobody puremagic.com
        ReportedBy: hsteoh quickfur.ath.cx



Test case:

void main() {                   
        int[dstring] map = ["abc"d: 123];
        foreach (key, val; map) {
                assert(map[key] == val); // throws RangeError ?!
        }
}


Changing dstring to string fixes the problem.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 15 2012
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512




Update: wstring keys fail the foreach test too:

int[wstring] map = ["abc"w: 1, "def"w: 2];
foreach (key, val; map) {
    assert((key in map) !is null); // throws AssertError
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512




OK, I've narrowed down this bug to using an AA literal for when the key is a
non-string array. For some strange reason, the AA literal *appears* to
correctly initialize the AA, as far as foreach can tell:

// CODE:
const int[] key1 = [1,2,3];
const int[] key2 = [1,2,4];
int[int[]] a5 = [
    key1 : 3,
    key2 : 4
];
foreach (key, val; a5) {
    writefln("%s -> %s", key, val);
}

// OUTPUT:
[1, 2, 3] -> 3
[1, 2, 4] -> 4

Seems to be correct, however:

// CODE:
foreach (key, val; a5) {
    assert(a5[key]==val);
}

// OUTPUT:
core.exception.AssertError aatest(15): Assertion failure

This is the failing case. However, if we *don't* use an AA literal:

// CODE:
const int[] key1 = [1,2,3];
const int[] key2 = [1,2,4];
int[int[]] a5;
a5[key1] = 3;
a5[key2] = 4;
foreach (key, val; a5) {
    assert(a5[key]==val);
}


Then there is no assertion failure.

Conclusion: something screwy is going on when an AA literal is used. The AA
appears to be initialized correctly, and foreach appears to return the correct
key/value pairs, *but* attempting to do lookups with the keys fails for some
unknown reason.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512




Even more weirdness:

int[int[]] a7;
const int[] key1 = [1,3,5];
const int[] key2 = [2,4,6];
a7[key1] = 135;
a7[key2] = 246;

int[int[]] a8 = [key1: 135, key2: 246];
assert(a7 == a8); // OK!
assert(a7[key1] == 135); // OK!
assert(a8[key1] == 135); // throws RangeError (?!)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512




Direct proof that something really weird is going on:

const int[] key1 = [1,3,5];
const int[] key2 = [2,4,6];
int[int[]] a8 = [ key1: 135, key2: 246 ];
a8[key1] = 135; // you'd think this should have no effect
foreach (key, val; a8) {
    // But you'd be wrong...
    writeln("%s -> %s", key, val);
}

// OUTPUT:
[2, 4, 6] -> 246
[1, 3, 5] -> 135
[1, 3, 5] -> 135

(Note the duplicated identical key->value pair.)

So the key/value pair initialized by the AA literal is somehow "different" from
the key/value pair assigned by "a8[key]=value;".

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512




Found cause of problem:

const int[] key = [1,2,3,4];
int[int[]] map1 = [ key: 1234 ];

// map1's internal hashtable has keyti pointing to typeid(const(int)[])

int[int[]] map2;
map2[key] = 1234;

// map2's internal hashtable has keyti pointing to typeid(int[])

This causes 'key' to map to a different hash value in map1 than in map2. So
far, no real problem yet. However, this:

map1[key] = 1234;

computes the hash value of 'key' using typeid(int[]).getHash(), NOT
typeid(const(int)[]).getHash(), causing a duplicate entry to appear in map1.
That is, the hash value of 'key' in the above line is exactly the same as the
hash value of key in "map2[key] = 1234". In fact, it seems that AA.get() and
AA[...] always uses the non-const typeinfo to compute the hash value, so it
will never find the keys created by the AA literal. The only time the entries
in the AA literal are actually visible is via foreach.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512




Apparently AA.get() and AA[key] *always* computes the hash value based on the
unqualified type, whereas AA literals use the const type which computes a
different hash value. For example:

int[dstring] map = ["abc"d: 1];
assert(map["abc"d]==1); // throws range error
assert(("abc"d in map) !is null); // assertion fails
map["abc"d] = 1; // creates duplicated entry (foreach finds "abc"d:1 twice)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 27 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512




Fixed in latest git:
https://github.com/D-Programming-Language/druntime/commit/96bc813e2a87a05da36b55274c44efd4e704417b

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 29 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512


hsteoh quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 29 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512


hsteoh quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |



Hmm, apparently Walter's hash fix wasn't enough. Something else is still going
wrong with the hash value somewhere.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 29 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512


hsteoh quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |FIXED



Actually nevermind that. We forgot to recompile phobos after recompiling
druntime, so the bad code was still lingering in there somewhere. Recompiling
phobos with the new runtime fixed everything.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 29 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7512


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |Justin.SpahrSummers gmail.c
                   |                            |om



*** Issue 4337 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 23 2012