Repository: numba/numba

Issue:
Cross target use of target-less `@overload` leads to lowering errors.
<!--

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/main/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'.

This incorrect use of `@overload` is actually a simplified version of the issue in #8529. Note that the `@overload` has no `target=` kwarg, as such the CUDA target cannot find it, but _also_ as the `target` is merely implied as CPU to preserve existing behaviours, this manifests as a lowering error as there's no `bar` function implementation in the target context for CUDA.
```python
import numpy as np
from numba.cuda import jit
from numba.extending import overload

def bar():
    pass


@overload(bar)
def ol_bar(x):
    def impl(x):
        return 12
    return impl


@jit
def call_bar(arr):
    arr[0] = bar(3)

tmp = np.zeros((1,))
call_bar[1, 1](tmp)
print(tmp)
```
The error message ends with:
```
NotImplementedError: No definition for lowering <... Closure>(int64,) -> Literal[int](12)
```
which is not ideal.

If the example is updated so that the overload is declared as `cpu` only via `@overload(bar, target='cpu')`, then the error message is more helpful:
```
Function resolution cannot find any matches for function '<function bar at 0x<snip>>` for the current target: '<class 'numba.core.target_extension.CUDA'>'.
```



Discussion:

Resolving patch:
diff --git a/numba/core/extending.py b/numba/core/extending.py
--- a/numba/core/extending.py
+++ b/numba/core/extending.py
@@ -53,8 +53,10 @@ def generic(self):
 
 
 # By default, an *overload* does not have a cpython wrapper because it is not
-# callable from python.
-_overload_default_jit_options = {'no_cpython_wrapper': True}
+# callable from python. It also has `nopython=True`, this has been default since
+# its inception!
+_overload_default_jit_options = {'no_cpython_wrapper': True,
+                                 'nopython':True}
 
 
 def overload(func, jit_options={}, strict=True, inline='never',
diff --git a/numba/core/typing/templates.py b/numba/core/typing/templates.py
--- a/numba/core/typing/templates.py
+++ b/numba/core/typing/templates.py
@@ -716,37 +716,30 @@ def _get_impl(self, args, kws):
     def _get_jit_decorator(self):
         """Gets a jit decorator suitable for the current target"""
 
-        jitter_str = self.metadata.get('target', None)
-        if jitter_str is None:
-            from numba import jit
-            # There is no target requested, use default, this preserves
-            # original behaviour
-            jitter = lambda *args, **kwargs: jit(*args, nopython=True, **kwargs)
-        else:
-            from numba.core.target_extension import (target_registry,
-                                                     get_local_target,
-                                                     jit_registry)
-
-            # target has been requested, see what it is...
-            jitter = jit_registry.get(jitter_str, None)
-
-            if jitter is None:
-                # No JIT known for target string, see if something is
-                # registered for the string and report if not.
-                target_class = target_registry.get(jitter_str, None)
-                if target_class is None:
-                    msg = ("Unknown target '{}', has it been ",
-                           "registered?")
-                    raise ValueError(msg.format(jitter_str))
-
-                target_hw = get_local_target(self.context)
-
-                # check that the requested target is in the hierarchy for the
-                # current frame's target.
-                if not issubclass(target_hw, target_class):
-                    msg = "No overloads exist for the requested target: {}."
-
-                jitter = jit_registry[target_hw]
+        from numba.core.target_extension import (target_registry,
+                                                 get_local_target,
+                                                 jit_registry)
+
+        jitter_str = self.metadata.get('target', 'generic')
+        jitter = jit_registry.get(jitter_str, None)
+
+        if jitter is None:
+            # No JIT known for target string, see if something is
+            # registered for the string and report if not.
+            target_class = target_registry.get(jitter_str, None)
+            if target_class is None:
+                msg = ("Unknown target '{}', has it been ",
+                       "registered?")
+                raise ValueError(msg.format(jitter_str))
+
+            target_hw = get_local_target(self.context)
+
+            # check that the requested target is in the hierarchy for the
+            # current frame's target.
+            if not issubclass(target_hw, target_class):
+                msg = "No overloads exist for the requested target: {}."
+
+            jitter = jit_registry[target_hw]
 
         if jitter is None:
             raise ValueError("Cannot find a suitable jit decorator")


Test patch: