Repository: numba/numba
Pull request: Raise specific error at typing time for iteration on >1D array.
As title.

Fixes #4508

<!--

Thanks for wanting to contribute to Numba :)

First, if you need some help or want to chat to the core developers, please
visit https://gitter.im/numba/numba for real time chat or post to the Numba
mailing list https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

Here's some guidelines to help the review process go smoothly.

0. Please write a description in this text box of the changes that are being
   made.

1. Please ensure that you have written units tests for the changes made/features
   added.

2. If you are closing an issue please use one of the automatic closing words as
   noted here: https://help.github.com/articles/closing-issues-using-keywords/

3. If your pull request is not ready for review but you want to make use of the
   continuous integration testing facilities please label it with `[WIP]` and
   then remove the label when you'd like it to be reviewed.

4. Once review has taken place please do not add features or make changes out of
   the scope of those requested by the reviewer (doing this just add delays as
   already reviewed code ends up having to be re-reviewed/it is hard to tell
   what is new etc!). Further, please do not rebase your branch on master/force
   push/rewrite history, doing any of these causes the context of any comments
   made by reviewers to be lost. If conflicts occur against master they should
   be resolved by merging master into the branch used for making the pull
   request.

Many thanks in advance for your cooperation!

-->


Problem statement:
LoweringError iterating over 2D array @numba.jit(nopython=True)
#### # FAILS: **This should not have happened**, a problem has occurred in Numba's internals.  You are currently using Numba version 0.45.1...LoweringError: Failed in nopython mode pipeline (step: nopython mode backend) iterating over 2D array...**Please report**...
a=numpy.array([[0, 1],[1, 3],[2, 2]])
@numba.jit(nopython=True)
def f(a):
..for i in a:
....print(i)
f(a)

#### # RUNS WITH A WARNING: Compilation is falling back to object mode WITH looplifting enabled because Function f failed at nopython mode lowering due to: iterating over 2D array
a=numpy.array([[0, 1],[1, 3],[2, 2]])
@numba.jit()
def f(a):
.. for i in a:
....print(i)
f(a)

### I figured out that the way to do what I need:
a=numpy.array([[0, 1],[1, 3],[2, 2]])
@numba.jit(nopython=True, nogil=True, cache=True)
def f(a):
..lst=[]
..for i in range(0,len(a)):
....lst.append(a[i,1])
..return lst(a)
f(a)
### filing the bug because is was requested by @numba.jit error message

Hints from issue discussion:

Commit message: Raise specific error at typing time for iteration on >1D array.

As title.

Fixes #4508

Patch to review:
diff --git a/numba/tests/test_iteration.py b/numba/tests/test_iteration.py
index 59c3c8f7391..2837a82cda2 100644
--- a/numba/tests/test_iteration.py
+++ b/numba/tests/test_iteration.py
@@ -4,7 +4,7 @@
 
 import numba.unittest_support as unittest
 from numba.compiler import compile_isolated, Flags
-from numba import numpy_support, types
+from numba import numpy_support, types, errors
 from .support import TestCase, MemoryLeakMixin, tag
 
 enable_pyobj_flags = Flags()
@@ -193,6 +193,24 @@ def test_array_1d_record_mutate_npm(self, flags=no_pyobj_flags):
     def test_array_1d_record_mutate(self):
         self.test_array_1d_record_mutate_npm(flags=force_pyobj_flags)
 
+    def test_array_2d_raises(self):
+
+        def foo(x):
+            for i in x:
+                pass
+
+        # 1D is fine
+        aryty = types.Array(types.int32, 1, 'C')
+        compile_isolated(foo, (aryty,))
+
+        # 2d is typing error
+        with self.assertRaises(errors.TypingError) as raises:
+            aryty = types.Array(types.int32, 2, 'C')
+            compile_isolated(foo, (aryty,))
+
+        self.assertIn("Direct iteration is not supported",
+                      str(raises.exception))
+
     def test_tuple_iter_issue1504(self):
         # The issue is due to `row` being typed as heterogeneous tuple.
         def bar(x, y):
diff --git a/numba/typing/builtins.py b/numba/typing/builtins.py
index 652ed788075..c4d405c4a5c 100644
--- a/numba/typing/builtins.py
+++ b/numba/typing/builtins.py
@@ -88,7 +88,16 @@ def generic(self, args, kws):
         assert not kws
         [obj] = args
         if isinstance(obj, types.IterableType):
-            return signature(obj.iterator_type, obj)
+            # raise this here to provide a very specific message about this
+            # common issue, delaying the error until later leads to something
+            # less specific being noted as the problem (e.g. no support for
+            # getiter on array(<>, 2, 'C')).
+            if isinstance(obj, types.Array) and obj.ndim > 1:
+                msg = ("Direct iteration is not supported for arrays with "
+                       "dimension > 1. Try using indexing instead?")
+                raise errors.TypingError(msg)
+            else:
+                return signature(obj.iterator_type, obj)
 
 
 @infer


Code review comments:
diff_hunk: @@ -88,7 +88,16 @@ def generic(self, args, kws):
         assert not kws
         [obj] = args
         if isinstance(obj, types.IterableType):
-            return signature(obj.iterator_type, obj)
+            # raise this here to provide a very specific message about this
path: numba/typing/builtins.py
text: @user1:
```suggestion
            # Raise this here to provide a very specific message about this
```

diff_hunk: @@ -88,7 +88,16 @@ def generic(self, args, kws):
         assert not kws
         [obj] = args
         if isinstance(obj, types.IterableType):
-            return signature(obj.iterator_type, obj)
+            # raise this here to provide a very specific message about this
+            # common issue, delaying the error until later leads to something
+            # less specific being noted as the problem (e.g. no support for
+            # getiter on array(<>, 2, 'C')).
+            if isinstance(obj, types.Array) and obj.ndim > 1:
+                msg = ("Direct iteration is not supported for arrays with "
+                       "dimension > 1. Try using indexing instead?")
path: numba/typing/builtins.py
text: @user1:
```suggestion
                       "dimension > 1. Try using indexing instead.")
```