Repository: numba/numba

Issue:
tuple getitem with unsigned index breaks parfors lowering
<!--

Thanks for opening an issue! To help the Numba team handle your information
efficiently, please first ensure that there is no other issue present that
already describes the issue you have
(search at https://github.com/numba/numba/issues?&q=is%3Aissue).

For more general "how do I do X?" type questions, please speak to us in real
time on https://gitter.im/numba/numba or post to the Numba mailing list
https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

-->

## Reporting a bug

<!--

Before submitting a bug report please ensure that you can check off these boxes:

-->

- [X] I am 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).

MWE:
```python
import numba as nb

def test1b():
    x = (1, 2, 3, 4, 5,)
    for i in nb.prange(len(x)):
        print(x[nb.types.uintp(i)])

nb.njit(test1b)() # broken
```
gives:
```
No definition for lowering <built-in function getitem>(tuple(int64 x 5), uint64) -> int64 
```
parfors generates unsigned `prange` indexes where possible, hence problem. Fix should be to just add `uintp` as a valid type to the tuple `operator.getitem,` lowering function.



Discussion:

Resolving patch:
diff --git a/numba/targets/tupleobj.py b/numba/targets/tupleobj.py
--- a/numba/targets/tupleobj.py
+++ b/numba/targets/tupleobj.py
@@ -202,7 +202,9 @@ def iternext_unituple(context, builder, sig, args, result):
 
 
 @lower_builtin(operator.getitem, types.UniTuple, types.intp)
+@lower_builtin(operator.getitem, types.UniTuple, types.uintp)
 @lower_builtin(operator.getitem, types.NamedUniTuple, types.intp)
+@lower_builtin(operator.getitem, types.NamedUniTuple, types.uintp)
 def getitem_unituple(context, builder, sig, args):
     tupty, _ = sig.args
     tup, idx = args


Test patch:
diff --git a/numba/tests/test_tuples.py b/numba/tests/test_tuples.py
--- a/numba/tests/test_tuples.py
+++ b/numba/tests/test_tuples.py
@@ -205,6 +205,12 @@ def test_index(self):
             cr.entry_point((), 0)
         self.assertEqual("tuple index out of range", str(raises.exception))
 
+        # test uintp indexing (because, e.g., parfor generates unsigned prange)
+        cr = compile_isolated(pyfunc,
+                              [types.UniTuple(types.int64, 3), types.uintp])
+        for i in range(len(tup)):
+            self.assertPreciseEqual(cr.entry_point(tup, types.uintp(i)), tup[i])
+
         # With a compile-time static index (the code generation path is different)
         pyfunc = tuple_index_static
         for typ in (types.UniTuple(types.int64, 4),
@@ -217,7 +223,6 @@ def test_index(self):
         with self.assertTypingError():
             cr = compile_isolated(pyfunc, (typ,))
 
-
     def test_in(self):
         pyfunc = in_usecase
         cr = compile_isolated(pyfunc,
@@ -355,6 +360,10 @@ def test_index(self):
         for i in range(len(p)):
             self.assertPreciseEqual(cfunc(p, i), pyfunc(p, i))
 
+        # test uintp indexing (because, e.g., parfor generates unsigned prange)
+        for i in range(len(p)):
+            self.assertPreciseEqual(cfunc(p, types.uintp(i)), pyfunc(p, i))
+
     def test_bool(self):
         def check(p):
             pyfunc = bool_usecase