Repository: numba/numba

Issue:
typed.Dict values() returns wrong results when dict key_type is np.int64
Hi,

I noticed the following issue in Numba typed.Dict: when using dict with key_type=np.int64 getting the values from it using corresponding view might return keys instead. The following simple test works as a reproducer for me:

```
    def test_numba_dict2(self):
        import numpy as np
        from collections import OrderedDict
        import numba
        from numba.typed import Dict
        def test_impl(data):

            value_counts_dict = Dict.empty(
                key_type=np.int64,
                value_type=types.intp
            )
            for key in data:
                value_counts_dict[key] = value_counts_dict.get(key, 0) + 1

            return value_counts_dict, list(value_counts_dict.keys()), list(value_counts_dict.values())
        jitted_func = numba.njit(test_impl)

        data_to_test = np.asarray([0, 1, -1], dtype=np.int64)
        results = jitted_func(data_to_test)
        expected_dict = OrderedDict([(0, 1), (1, 1), (-1, 1)])
        print("DEBUG: results=", results)
        self.assertEqual(results[0], expected_dict)
        self.assertEqual(results[1], list(expected_dict.keys()))
        self.assertEqual(results[2], list(expected_dict.values()))
```
producing the following output:

> DEBUG: results= (DictType[int64,int64]({0: 1, 1: 1, -1: 1}), [0, 1, -1], [0, 1, -1])
> FAIL: test_numba_dict2 (sdc.tests.test_numba.TestNumba)
> Traceback (most recent call last):
>   File "C:\Users\akozlov\AppData\Local\Continuum\anaconda3\hpat\sdc\tests\test_numba.py", l
> ine 308, in test_numba_dict2
>     self.assertEqual(results[2], list(expected_dict.values()))
> AssertionError: Lists differ: [0, 1, -1] != [1, 1, 1]
> 

At the same time if key_type and dtype of data_to_test are np.int32 the test passes:

> DEBUG: results= (DictType[int32,int64]({0: 1, 1: 1, -1: 1}), [0, 1, -1], [1, 1, 1])
> Ran 1 test in 0.994s
> 
> OK
> 

I suspect some memory corruption, since it's not always a case of obtaining incorrect values from the correct dictionary, but it might also be that the computed dictionary itself is corrupted:
```
    def test_numba_dict3(self):
        import numpy as np
        from collections import OrderedDict
        import numba
        from numba.typed import Dict
        def test_impl(data):

            value_counts_dict = Dict.empty(
                key_type=np.int64,
                value_type=types.intp
            )
            for key in data:
                value_counts_dict[key] = value_counts_dict.get(key, 0) + 1

            dict_values = list(value_counts_dict.values())
            return value_counts_dict, dict_values
        jitted_func = numba.njit(test_impl)

        data_to_test = np.asarray([0, 1, -1], dtype=np.int64)
        results = jitted_func(data_to_test)
        expected_dict = OrderedDict([(0, 1), (1, 1), (-1, 1)])
        print("DEBUG: results=", results)
        self.assertEqual(results[0], expected_dict)
        self.assertEqual(results[1], list(expected_dict.values()))
```

gives:

> DEBUG: results= (DictType[int64,int64]({1: 1, 1: 1, 1: 1}), [1, 1, 1])
> FAIL: test_numba_dict3 (sdc.tests.test_numba.TestNumba)
> Traceback (most recent call last):
>   File "C:\Users\akozlov\AppData\Local\Continuum\anaconda3\hpat\sdc\tests\test_numba.py", l
> ine 333, in test_numba_dict3
>     self.assertEqual(results[0], expected_dict)
> AssertionError: DictType[int64,int64]({1: 1, 1: 1, 1: 1}) != OrderedDict([(0, 1), (1, 1), (
> -1, 1)])
> 
> Ran 1 test in 1.017s
> 
> FAILED (failures=1)


I was using Numba:
# Name                    Version                   Build  Channel
numba                     0.47.0.dev0+710.g18fe91598           dev_0    <develop>

Specifically the following commit:
commit 18fe9159849a0d512f1fb284d7cdc6bbf72ceab3 (HEAD -> sdc/latest)

Best Regards,
Alexey.

Discussion:

Patch:
diff --git a/numba/core/types/containers.py b/numba/core/types/containers.py
index e9cc0ed2f..fa6ebd394 100644
--- a/numba/core/types/containers.py
+++ b/numba/core/types/containers.py
@@ -624,6 +624,7 @@ class DictItemsIterableType(SimpleIterableType):
         self.parent = parent
         self.yield_type = self.parent.keyvalue_type
         name = "items[{}]".format(self.parent.name)
+        self.name = name
         iterator_type = DictIteratorType(self)
         super(DictItemsIterableType, self).__init__(name, iterator_type)
 
@@ -636,6 +637,7 @@ class DictKeysIterableType(SimpleIterableType):
         self.parent = parent
         self.yield_type = self.parent.key_type
         name = "keys[{}]".format(self.parent.name)
+        self.name = name
         iterator_type = DictIteratorType(self)
         super(DictKeysIterableType, self).__init__(name, iterator_type)
 
@@ -648,6 +650,7 @@ class DictValuesIterableType(SimpleIterableType):
         self.parent = parent
         self.yield_type = self.parent.value_type
         name = "values[{}]".format(self.parent.name)
+        self.name = name
         iterator_type = DictIteratorType(self)
         super(DictValuesIterableType, self).__init__(name, iterator_type)
 
@@ -657,5 +660,6 @@ class DictIteratorType(SimpleIteratorType):
         self.parent = iterable.parent
         self.iterable = iterable
         yield_type = iterable.yield_type
-        name = "iter[{}->{}]".format(iterable.parent, yield_type)
+        name = "iter[{}->{}],{}".format(iterable.parent, yield_type,
+                                        iterable.name)
         super(DictIteratorType, self).__init__(name, yield_type)


Test patch:
diff --git a/numba/tests/test_dictobject.py b/numba/tests/test_dictobject.py
index daaaf559c..90bf3cbec 100644
--- a/numba/tests/test_dictobject.py
+++ b/numba/tests/test_dictobject.py
@@ -1599,3 +1599,33 @@ class TestNoJit(TestCase):
             with forbid_codegen():
                 d = Dict.empty(types.int32, types.float32)
                 self.assertEqual(type(d), dict)
+
+
+class TestDictIterator(TestCase):
+    def test_dict_iterator(self):
+        @njit
+        def fun1():
+            dd = Dict.empty(key_type=types.intp,
+                            value_type=types.intp)
+            dd[0] = 10
+            dd[1] = 20
+            dd[2] = 30
+
+            return list(dd.keys()), list(dd.values())
+
+        @njit
+        def fun2():
+            dd = Dict.empty(key_type=types.intp,
+                            value_type=types.intp)
+            dd[4] = 77
+            dd[5] = 88
+            dd[6] = 99
+
+            return list(dd.keys()), list(dd.values())
+        res1 = fun1()
+        res2 = fun2()
+
+        self.assertEqual([0,1,2], res1[0])
+        self.assertEqual([10,20,30], res1[1])
+        self.assertEqual([4,5,6], res2[0])
+        self.assertEqual([77,88,99], res2[1])