Repository: numba/numba

Issue:
Cannot iterate over fields of record array
When iterating over the fields of a record array, numba complains about a not implemented getitem. 
Accessing the fields by name outside a loop works. I am using numba 0.52, the problem occurs on both Windows and linux

## This is the ipython cell that produces the error:

```python
%pylab
import numpy.random
from numba import njit

@njit
def recarriterator(rec):
    for o in 'a','b','c':
        print(rec[o][0])
    return
        
@njit
def recarriterator2(rec):
    print(rec['a'][0])
    print(rec['b'][0])
    print(rec['c'][0])
    return
        
ldd=[]
ldk=[]
keys='a','b','c'
for o in keys:
    #if not (o == 'observation_id' or o == 'report_id' or o == 'sensor_id' or o == 'source_id'):
        ldd.append(random.rand(5))
        ldk.append((o,ldd[-1].dtype))
rec = numpy.rec.fromarrays(ldd, dtype=ldk)
    
recarriterator2(rec)
recarriterator(rec)
```
## The error code:
```
Using matplotlib backend: Qt5Agg
Populating the interactive namespace from numpy and matplotlib
0.26156099390229226
0.4919898206995005
0.363624558244539
---------------------------------------------------------------------------
TypingError                               Traceback (most recent call last)
<ipython-input-1-56c6c55bddcf> in <module>
     26 
     27 recarriterator2(rec)
---> 28 recarriterator(rec)

~\anaconda3\lib\site-packages\numba\core\dispatcher.py in _compile_for_args(self, *args, **kws)
    413                 e.patch_message(msg)
    414 
--> 415             error_rewrite(e, 'typing')
    416         except errors.UnsupportedError as e:
    417             # Something unsupported is present in the user code, add help info

~\anaconda3\lib\site-packages\numba\core\dispatcher.py in error_rewrite(e, issue_type)
    356                 raise e
    357             else:
--> 358                 reraise(type(e), e, None)
    359 
    360         argtypes = []

~\anaconda3\lib\site-packages\numba\core\utils.py in reraise(tp, value, tb)
     78         value = tp()
     79     if value.__traceback__ is not tb:
---> 80         raise value.with_traceback(tb)
     81     raise value
     82 

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function getitem>) found for signature:
 
 >>> getitem(unaligned array(Record(a[type=float64;offset=0],b[type=float64;offset=8],c[type=float64;offset=16];24;False), 1d, C), unicode_type)
 
There are 22 candidate implementations:
  - Of which 20 did not match due to:
  Overload of function 'getitem': File: <numerous>: Line N/A.
    With argument(s): '(unaligned array(Record(a[type=float64;offset=0],b[type=float64;offset=8],c[type=float64;offset=16];24;False), 1d, C), unicode_type)':
   No match.
  - Of which 2 did not match due to:
  Overload in function 'GetItemBuffer.generic': File: numba\core\typing\arraydecl.py: Line 162.
    With argument(s): '(unaligned array(Record(a[type=float64;offset=0],b[type=float64;offset=8],c[type=float64;offset=16];24;False), 1d, C), unicode_type)':
   Rejected as the implementation raised a specific error:
     TypeError: unsupported array index type unicode_type in [unicode_type]
  raised from C:\Users\leopo\anaconda3\lib\site-packages\numba\core\typing\arraydecl.py:68

During: typing of intrinsic-call at <ipython-input-1-56c6c55bddcf> (8)

File "<ipython-input-1-56c6c55bddcf>", line 8:
def recarriterator(rec):
    <source elided>
    for o in 'a','b','c':
        print(rec[o][0])
        ^
```

Discussion:

Patch:
diff --git a/numba/core/untyped_passes.py b/numba/core/untyped_passes.py
index 7e90b58aa..358f06ffa 100644
--- a/numba/core/untyped_passes.py
+++ b/numba/core/untyped_passes.py
@@ -1464,6 +1464,9 @@ class LiteralUnroll(FunctionPass):
         pm.add_pass(RewriteSemanticConstants, "rewrite semantic constants")
         # do the unroll
         pm.add_pass(MixedContainerUnroller, "performs mixed container unroll")
+        # rewrite dynamic getitem to static getitem as it's possible some more
+        # getitems will now be statically resolvable
+        pm.add_pass(GenericRewrites, "Generic Rewrites")
         pm.finalize()
         pm.run(state)
         return True


Test patch:
diff --git a/numba/tests/test_record_dtype.py b/numba/tests/test_record_dtype.py
index 4e5033d6d..61109a7fe 100644
--- a/numba/tests/test_record_dtype.py
+++ b/numba/tests/test_record_dtype.py
@@ -1103,6 +1103,26 @@ class TestRecordArrayGetItem(unittest.TestCase):
         self.assertIn("Field 'f' was not found in record with fields "
                       "('first', 'second')", str(raises.exception))
 
+    def test_literal_unroll_dynamic_to_static_getitem_transform(self):
+        # See issue #6634
+        keys = ('a', 'b', 'c')
+        n = 5
+
+        def pyfunc(rec):
+            x = np.zeros((n,))
+            for o in literal_unroll(keys):
+                x += rec[o]
+            return x
+
+        dt = np.float64
+        ldd = [np.arange(dt(n)) for x in keys]
+        ldk = [(x, np.float64,) for x in keys]
+        rec = np.rec.fromarrays(ldd, dtype=ldk)
+
+        expected = pyfunc(rec)
+        got = njit(pyfunc)(rec)
+        np.testing.assert_allclose(expected, got)
+
 
 class TestRecordArraySetItem(unittest.TestCase):
     """