Repository: numba/numba

Issue:
Slicing array[:0] fails with parallel=True in 0.41
<!--

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).

<!--

Please include details of the bug here, including, if applicable, what you
expected to happen!

-->

The following code throws an error with version `0.41`. It passes in `0.40.1`. It also passes in both versions if we set `parallel=False`

```python
from numba import njit
import numpy as np

@njit(parallel=True)
def g():
    a = np.zeros(10, dtype=np.int32)
    a[:0] += 1

g()
```

```
Traceback (most recent call last):
  File "numba_lol.py", line 9, in <module>
    g()
AssertionError: Sizes of a, $0.17 do not match on numba_lol.py (7)
```



Discussion:
Thanks for the report. I think this is a duplicate of a known bug https://github.com/numba/numba/issues/3461

Resolving patch:
diff --git a/numba/array_analysis.py b/numba/array_analysis.py
--- a/numba/array_analysis.py
+++ b/numba/array_analysis.py
@@ -1244,7 +1244,7 @@ def _analyze_op_binop(self, scope, equiv_set, expr):
         return self._analyze_broadcast(scope, equiv_set, expr.loc, [expr.lhs, expr.rhs])
 
     def _analyze_op_inplace_binop(self, scope, equiv_set, expr):
-        require(expr.immutable_fn in INPLACE_BINARY_MAP_OP)
+        require(expr.fn in INPLACE_BINARY_MAP_OP)
         return self._analyze_broadcast(scope, equiv_set, expr.loc, [expr.lhs, expr.rhs])
 
     def _analyze_op_arrayexpr(self, scope, equiv_set, expr):


Test patch:
diff --git a/numba/tests/test_array_analysis.py b/numba/tests/test_array_analysis.py
--- a/numba/tests/test_array_analysis.py
+++ b/numba/tests/test_array_analysis.py
@@ -123,7 +123,7 @@ def stage_array_analysis():
 
         pm.add_stage(stage_array_analysis, "analyze array equivalences")
         if test_idempotence:
-            # Do another pass of array analysis to test idempontence
+            # Do another pass of array analysis to test idempotence
             pm.add_stage(stage_array_analysis, "analyze array equivalences")
 
         pm.finalize()
@@ -537,6 +537,23 @@ def test_8(m):
                                asserts=[self.without_assert('B', 'C')],
                                idempotent=False)
 
+        def test_9(m):
+            # issues #3461 and #3554, checks equivalence on empty slices
+            # and across binop
+            A = np.zeros((m))
+            B = A[:0] # B = array([], dtype=int64)
+            C = A[1:]
+            D = A[:-1:-1] # D = array([], dtype=int64)
+            E = B + D
+            F = E
+            F += 1 # F = array([], dtype=int64)
+            return A, C, F
+        self._compile_and_test(test_9, (types.intp,),
+                               equivs=[self.without_equiv('B', 'C'),
+                                       self.with_equiv('A', 'm'),
+                                       self.with_equiv('B', 'D'),
+                                       self.with_equiv('F', 'D'),],)
+
     def test_numpy_calls(self):
         def test_zeros(n):
             a = np.zeros(n)
diff --git a/numba/tests/test_parfors.py b/numba/tests/test_parfors.py
--- a/numba/tests/test_parfors.py
+++ b/numba/tests/test_parfors.py
@@ -2426,6 +2426,16 @@ def test_impl():
 
         self.check(test_impl)
 
+    @skip_unsupported
+    def test_parfor_slice19(self):
+        # issues #3561 and #3554, empty slice binop
+        def test_impl(X):
+            X[:0] += 1
+            return X
+
+        self.check(test_impl, np.ones(10))
+
+
 class TestParforsOptions(TestParforsBase):
 
     def check(self, pyfunc, *args, **kwargs):