Repository: numba/numba

Issue:
No error for jit(nopython=True, forceobj=True)
- [ 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).

When using the `jit` decorator with both `nopython=True` and `forceobj=True` no error is reported, despite these flags probably being mutually exclusive.
```python
import numba

@numba.jit(nopython=True, forceobj=True)
def f():
    pass

f()
```
The prior example runs without complaints. If the `njit` decorator is used instead, appropriate warnings are thrown.

Discussion:

Patch:
diff --git a/numba/core/decorators.py b/numba/core/decorators.py
index 5ea8bbbbb..ba0125c16 100644
--- a/numba/core/decorators.py
+++ b/numba/core/decorators.py
@@ -143,6 +143,8 @@ def jit(signature_or_function=None, locals={}, target='cpu', cache=False,
         raise DeprecationError(_msg_deprecated_signature_arg.format('argtypes'))
     if 'restype' in options:
         raise DeprecationError(_msg_deprecated_signature_arg.format('restype'))
+    if options.get('nopython', False) and options.get('forceobj', False):
+        raise ValueError("Only one of 'nopython' or 'forceobj' can be True.")
 
     options['boundscheck'] = boundscheck
 
@@ -232,6 +234,7 @@ def njit(*args, **kws):
         warnings.warn('nopython is set for njit and is ignored', RuntimeWarning)
     if 'forceobj' in kws:
         warnings.warn('forceobj is set for njit and is ignored', RuntimeWarning)
+        del kws['forceobj']
     kws.update({'nopython': True})
     return jit(*args, **kws)
 


Test patch:
diff --git a/numba/tests/test_api.py b/numba/tests/test_api.py
index 4e3d67a72..b156ceb6a 100644
--- a/numba/tests/test_api.py
+++ b/numba/tests/test_api.py
@@ -1,4 +1,7 @@
+import warnings
+
 import numba
+from numba import jit, njit
 
 from numba.tests.support import TestCase
 import unittest
@@ -28,5 +31,60 @@ class TestNumbaModule(TestCase):
         numba.__version__  # not in __all__
 
 
+class TestJitDecorator(TestCase):
+    """
+    Test the jit and njit decorators
+    """
+    def test_jit_nopython_forceobj(self):
+        with self.assertRaises(ValueError) as cm:
+            jit(nopython=True, forceobj=True)
+        self.assertIn(
+            "Only one of 'nopython' or 'forceobj' can be True.",
+            str(cm.exception)
+        )
+
+        def py_func(x):
+            return x
+
+        jit_func = jit(nopython=True)(py_func)
+        jit_func(1)
+        # Check length of nopython_signatures to check
+        # which mode the function was compiled in
+        self.assertEqual(len(jit_func.nopython_signatures), 1)
+
+        jit_func = jit(forceobj=True)(py_func)
+        jit_func(1)
+        self.assertEqual(len(jit_func.nopython_signatures), 0)
+
+    def test_njit_nopython_forceobj(self):
+        with warnings.catch_warnings(record=True) as w:
+            warnings.simplefilter('always', RuntimeWarning)
+            njit(forceobj=True)
+        self.assertEqual(len(w), 1)
+        self.assertIn(
+            'forceobj is set for njit and is ignored', str(w[0].message)
+        )
+
+        with warnings.catch_warnings(record=True) as w:
+            warnings.simplefilter('always', RuntimeWarning)
+            njit(nopython=True)
+        self.assertEqual(len(w), 1)
+        self.assertIn(
+            'nopython is set for njit and is ignored', str(w[0].message)
+        )
+
+        def py_func(x):
+            return x
+
+        jit_func = njit(nopython=True)(py_func)
+        jit_func(1)
+        self.assertEqual(len(jit_func.nopython_signatures), 1)
+
+        jit_func = njit(forceobj=True)(py_func)
+        jit_func(1)
+        # Since forceobj is ignored this has to compile in nopython mode
+        self.assertEqual(len(jit_func.nopython_signatures), 1)
+
+
 if __name__ == '__main__':
     unittest.main()