Repository: numba/numba

Issue:
`ListType` needs to implement `key`
- [x] I have tried using the latest released version of Numba (most recent is
 visible in the change log (https://github.com/numba/numba/blob/master/CHANGE_LOG).
- [x] I have included below a minimal working reproducer (if you are unsure how
 to write one see http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports).

Currently `ListType` cannot cope with parametrized types that do not have unique names because `ListType.key` is not implemented. The example below fails with `TypingError` when it tries to reuse the implementation of `l1.append` for `l2.append`:
```python
from numba import jit, types
from numba.core.datamodel.models import IntegerModel
from numba.extending import register_model
from numba.typed import List

class MyParametrizedType(types.Type):
    def __init__(self, n):
        super(MyParametrizedType, self).__init__('MyParametrizedType')  # <- type name does not contain n
        self.n = n
        self.bitwidth = 64

    @property
    def key(self):
        return self.n

register_model(MyParametrizedType)(IntegerModel)

xty, yty = MyParametrizedType(1), MyParametrizedType(2)

@jit(types.void(xty, yty), nopython=True, no_cpython_wrapper=True)  # <- fails with TypingError
def get_unit_system_data(x, y):
    l1 = List.empty_list(xty)
    l2 = List.empty_list(yty)

    l1.append(x)
    l2.append(y)
```
This likely affects the corresponding iterable and iterator types as well. `ListType.key` should probably look like:
```python
@property
def key(self):
    return self.item_type
```



Discussion:

Patch:
diff --git a/numba/core/types/containers.py b/numba/core/types/containers.py
index 6191852af..e16aae402 100644
--- a/numba/core/types/containers.py
+++ b/numba/core/types/containers.py
@@ -627,6 +627,10 @@ class ListType(IterableType):
         name = "{}[{}]".format(self.__class__.__name__, itemty,)
         super(ListType, self).__init__(name)
 
+    @property
+    def key(self):
+        return self.item_type
+
     def is_precise(self):
         return not isinstance(self.item_type, Undefined)
 
diff --git a/numba/cuda/api.py b/numba/cuda/api.py
index 795f6450e..28c4a8bf9 100644
--- a/numba/cuda/api.py
+++ b/numba/cuda/api.py
@@ -129,9 +129,6 @@ def managed_array(shape, dtype=np.float, strides=None, order='C', stream=0,
     Allocate a np.ndarray with a buffer that is managed.
     Similar to np.empty().
 
-    Managed memory is supported on Linux, and is considered experimental on
-    Windows.
-
     :param attach_global: A flag indicating whether to attach globally. Global
                           attachment implies that the memory is accessible from
                           any stream on any device. If ``False``, attachment is


Test patch:
diff --git a/numba/cuda/tests/cudadrv/test_managed_alloc.py b/numba/cuda/tests/cudadrv/test_managed_alloc.py
index 03b996216..2e45c2292 100644
--- a/numba/cuda/tests/cudadrv/test_managed_alloc.py
+++ b/numba/cuda/tests/cudadrv/test_managed_alloc.py
@@ -1,4 +1,5 @@
 import numpy as np
+import platform
 from ctypes import byref, c_size_t
 from numba.cuda.cudadrv.driver import device_memset, driver
 from numba import cuda
@@ -8,7 +9,6 @@ from numba.tests.support import linux_only
 
 
 @skip_on_cudasim('CUDA Driver API unsupported in the simulator')
-@linux_only
 class TestManagedAlloc(ContextResettingTestCase):
 
     def get_total_gpu_memory(self):
@@ -57,8 +57,12 @@ class TestManagedAlloc(ContextResettingTestCase):
     def test_managed_alloc_driver_oversubscribe(self):
         msg = "Oversubscription of managed memory unsupported prior to CC 6.0"
         self.skip_if_cc_major_lt(6, msg)
+        if platform.system() != "Linux":
+            msg = "Oversubscription of managed memory only supported on Linux"
+            self.skipTest(msg)
         self._test_managed_alloc_driver(2.0)
 
+    @linux_only
     def test_managed_alloc_driver_host_attach(self):
         msg = "Host attached managed memory is not accessible prior to CC 6.0"
         self.skip_if_cc_major_lt(6, msg)
@@ -111,6 +115,7 @@ class TestManagedAlloc(ContextResettingTestCase):
     def test_managed_array_attach_global(self):
         self._test_managed_array()
 
+    @linux_only
     def test_managed_array_attach_host(self):
         self._test_managed_array()
         msg = "Host attached managed memory is not accessible prior to CC 6.0"
diff --git a/numba/tests/test_types.py b/numba/tests/test_types.py
index c1c967b09..9a9818cb7 100644
--- a/numba/tests/test_types.py
+++ b/numba/tests/test_types.py
@@ -874,6 +874,27 @@ class TestIssues(TestCase):
                 self.assertIs(
                     types.TypeRef(ty1) == types.TypeRef(ty2), ty1 == ty2)
 
+    def test_issue_list_type_key(self):
+        # https://github.com/numba/numba/issues/6397
+        class NoUniqueNameType(types.Dummy):
+            def __init__(self, param):
+                super(NoUniqueNameType, self).__init__('NoUniqueNameType')
+                self.param = param
+
+            @property
+            def key(self):
+                return self.param
+
+        no_unique_name_type_1 = NoUniqueNameType(1)
+        no_unique_name_type_2 = NoUniqueNameType(2)
+
+        for ty1 in (no_unique_name_type_1, no_unique_name_type_2):
+            for ty2 in (no_unique_name_type_1, no_unique_name_type_2):
+                self.assertIs(
+                    types.ListType(ty1) == types.ListType(ty2),  # noqa: E721
+                    ty1 == ty2
+                )
+
 
 if __name__ == '__main__':
     unittest.main()