Repository: numba/numba

Issue:
objmode error in IR legalization
<!--

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).

-->

## Reporting a bug

<!--

Before submitting a bug report please ensure that you can check off these boxes:

-->

- [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 a self contained code sample to reproduce the problem.
  i.e. it's possible to run as 'python bug.py'.

<!--

Please include details of the bug here, including, if applicable, what you
expected to happen!

-->
Looks like IR legalization is called on objmode IR, potentially throwing error for valid code. Is IR legalization pass needed for objmode IR in general?
```python
import numba
import numpy as np

@numba.njit
def f(A):
    with numba.objmode(B="int64[::1]"):
        B = A.view("int64")
    return B

f(np.ones(11, np.int64))
```
```
  File "/Users/ehsan/dev/numba/numba/core/typeinfer.py", line 1071, in propagate
    raise errors[0]
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: Handle with contexts)
Failed in nopython mode pipeline (step: nopython frontend)
Failed in object mode pipeline (step: ensure IR is legal prior to lowering)
'view' can only be called on NumPy dtypes, try wrapping the variable 'A' with 'np.<dtype>()'

File "../tmp/objmode_ir_legal.py", line 7:
def f(A):
    <source elided>
    with numba.objmode(B="int64[::1]"):
        B = A.view("int64")
        ^

During: resolving callee type: type(ObjModeLiftedWith(<function f at 0x10180d040>))
During: typing of call at /Users/ehsan/dev/bodo/../tmp/objmode_ir_legal.py (6)


File "../tmp/objmode_ir_legal.py", line 6:
def f(A):
    with numba.objmode(B="int64[::1]"):
    ^
```


Discussion:
@ehsantn thank you for reporting this! I can confirm I am able to reproduce this.
This should be easy enough to fix over the RC period.

Note: IRLegalization should not check for unsupported nopython-mode feature in objmode.

Resolving patch:
diff --git a/numba/core/compiler.py b/numba/core/compiler.py
--- a/numba/core/compiler.py
+++ b/numba/core/compiler.py
@@ -28,7 +28,9 @@
                                      ParforPass, DumpParforDiagnostics,
                                      IRLegalization, NoPythonBackend,
                                      InlineOverloads, PreLowerStripPhis,
-                                     NativeLowering)
+                                     NativeLowering,
+                                     NoPythonSupportedFeatureValidation,
+                                     )
 
 from numba.core.object_mode_passes import (ObjectModeFrontEnd,
                                            ObjectModeBackEnd)
@@ -547,6 +549,8 @@ def define_nopython_pipeline(state, name='nopython'):
     def define_nopython_lowering_pipeline(state, name='nopython_lowering'):
         pm = PassManager(name)
         # legalise
+        pm.add_pass(NoPythonSupportedFeatureValidation,
+                    "ensure features that are in use are in a valid form")
         pm.add_pass(IRLegalization,
                     "ensure IR is legal prior to lowering")
 
diff --git a/numba/core/typed_passes.py b/numba/core/typed_passes.py
--- a/numba/core/typed_passes.py
+++ b/numba/core/typed_passes.py
@@ -437,9 +437,11 @@ def run_pass(self, state):
 
 
 @register_pass(mutates_CFG=False, analysis_only=True)
-class IRLegalization(AnalysisPass):
+class NoPythonSupportedFeatureValidation(AnalysisPass):
+    """NoPython Mode check: Validates the IR to ensure that features in use are
+    in a form that is supported"""
 
-    _name = "ir_legalization"
+    _name = "nopython_supported_feature_validation"
 
     def __init__(self):
         AnalysisPass.__init__(self)
@@ -447,6 +449,18 @@ def __init__(self):
     def run_pass(self, state):
         raise_on_unsupported_feature(state.func_ir, state.typemap)
         warn_deprecated(state.func_ir, state.typemap)
+        return False
+
+
+@register_pass(mutates_CFG=False, analysis_only=True)
+class IRLegalization(AnalysisPass):
+
+    _name = "ir_legalization"
+
+    def __init__(self):
+        AnalysisPass.__init__(self)
+
+    def run_pass(self, state):
         # NOTE: this function call must go last, it checks and fixes invalid IR!
         check_and_legalize_ir(state.func_ir)
         return True


Test patch:
diff --git a/numba/tests/test_withlifting.py b/numba/tests/test_withlifting.py
--- a/numba/tests/test_withlifting.py
+++ b/numba/tests/test_withlifting.py
@@ -1083,6 +1083,20 @@ def test4():
              r"as a (<class ')?numba.typed.typedlist.List('>)?"),
         )
 
+    def test_objmode_use_of_view(self):
+        # See issue #7158, npm functionality should only be validated if in
+        # npm.
+        @njit
+        def foo(x):
+            with numba.objmode(y="int64[::1]"):
+                y = x.view("int64")
+            return y
+
+        a = np.ones(1, np.int64).view('float64')
+        expected = foo.py_func(a)
+        got = foo(a)
+        self.assertPreciseEqual(expected, got)
+
 
 def case_inner_pyfunc(x):
     return x / 10