Repository: numba/numba

Issue:
Regression in keyword arguments handling
When upgrading to numba 0.25.0, the following code began to fail, whereas it previously executed correctly using numba 0.23.1:

```
import numba as nb
import numpy as np

@nb.njit
def bisect_right(a, x, lo=0, hi=None):
    if hi is None:
        hi = a.shape[0]
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]: hi = mid
        else: lo = mid+1
    return lo

a = np.arange(100, dtype=np.int64)
bisect_right(a, 10)
```

It now fails with the following traceback:

``` python
---------------------------------------------------------------------------
LoweringError                             Traceback (most recent call last)
<ipython-input-1-8b4f39ee75a4> in <module>()
     13 
     14 a = np.arange(100, dtype=np.int64)
---> 15 bisect_right(a, 10)

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/dispatcher.py in _compile_for_args(self, *args, **kws)
    286             else:
    287                 real_args.append(self.typeof_pyval(a))
--> 288         return self.compile(tuple(real_args))
    289 
    290     def inspect_llvm(self, signature=None):

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/dispatcher.py in compile(self, sig)
    504 
    505             self._cache_misses[sig] += 1
--> 506             cres = self._compiler.compile(args, return_type)
    507             self.add_overload(cres)
    508             self._cache.save_overload(sig, cres)

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/dispatcher.py in compile(self, args, return_type)
     83                                       impl,
     84                                       args=args, return_type=return_type,
---> 85                                       flags=flags, locals=self.locals)
     86         # Check typing error if object mode is used
     87         if cres.typing_error is not None and not flags.enable_pyobject:

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library)
    688     pipeline = Pipeline(typingctx, targetctx, library,
    689                         args, return_type, flags, locals)
--> 690     return pipeline.compile_extra(func)
    691 
    692 

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in compile_extra(self, func)
    376                 raise e
    377 
--> 378         return self.compile_bytecode(bc, func_attr=self.func_attr)
    379 
    380     def compile_bytecode(self, bc, lifted=(), lifted_from=None,

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in compile_bytecode(self, bc, lifted, lifted_from, func_attr)
    385         self.lifted_from = lifted_from
    386         self.func_attr = func_attr
--> 387         return self._compile_bytecode()
    388 
    389     def compile_internal(self, bc, func_attr=DEFAULT_FUNCTION_ATTRIBUTES):

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in _compile_bytecode(self)
    669 
    670         pm.finalize()
--> 671         res = pm.run(self.status)
    672         if res is not None:
    673             # Early pipeline completion

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in run(self, status)
    255                     # No more fallback pipelines?
    256                     if is_final_pipeline:
--> 257                         raise patched_exception
    258                     # Go to next fallback pipeline
    259                     else:

LoweringError: Caused By:
Traceback (most recent call last):
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 249, in run
    stage()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 616, in stage_nopython_backend
    self._backend(lowerfn, objectmode=False)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 571, in _backend
    lowered = lowerfn()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 558, in backend_nopython_mode
    self.flags)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 816, in native_lowering_stage
    lower.lower()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 123, in lower
    self.lower_normal_function(self.fndesc)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 158, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 183, in lower_function_body
    self.lower_block(block)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 201, in lower_block
    raise LoweringError(msg, inst.loc)
LoweringError: Internal error:
NotImplementedError: ?int64 as constant unsupported
File "<ipython-input-1-8b4f39ee75a4>", line 6

Failed at nopython (nopython mode backend)
Internal error:
NotImplementedError: ?int64 as constant unsupported
File "<ipython-input-1-8b4f39ee75a4>", line 6
```

The code also fails with numba 0.24.0 as well as the latest dev build (0.26.0.dev-np110py27_128)

Regression in keyword arguments handling
When upgrading to numba 0.25.0, the following code began to fail, whereas it previously executed correctly using numba 0.23.1:

```
import numba as nb
import numpy as np

@nb.njit
def bisect_right(a, x, lo=0, hi=None):
    if hi is None:
        hi = a.shape[0]
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]: hi = mid
        else: lo = mid+1
    return lo

a = np.arange(100, dtype=np.int64)
bisect_right(a, 10)
```

It now fails with the following traceback:

``` python
---------------------------------------------------------------------------
LoweringError                             Traceback (most recent call last)
<ipython-input-1-8b4f39ee75a4> in <module>()
     13 
     14 a = np.arange(100, dtype=np.int64)
---> 15 bisect_right(a, 10)

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/dispatcher.py in _compile_for_args(self, *args, **kws)
    286             else:
    287                 real_args.append(self.typeof_pyval(a))
--> 288         return self.compile(tuple(real_args))
    289 
    290     def inspect_llvm(self, signature=None):

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/dispatcher.py in compile(self, sig)
    504 
    505             self._cache_misses[sig] += 1
--> 506             cres = self._compiler.compile(args, return_type)
    507             self.add_overload(cres)
    508             self._cache.save_overload(sig, cres)

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/dispatcher.py in compile(self, args, return_type)
     83                                       impl,
     84                                       args=args, return_type=return_type,
---> 85                                       flags=flags, locals=self.locals)
     86         # Check typing error if object mode is used
     87         if cres.typing_error is not None and not flags.enable_pyobject:

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library)
    688     pipeline = Pipeline(typingctx, targetctx, library,
    689                         args, return_type, flags, locals)
--> 690     return pipeline.compile_extra(func)
    691 
    692 

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in compile_extra(self, func)
    376                 raise e
    377 
--> 378         return self.compile_bytecode(bc, func_attr=self.func_attr)
    379 
    380     def compile_bytecode(self, bc, lifted=(), lifted_from=None,

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in compile_bytecode(self, bc, lifted, lifted_from, func_attr)
    385         self.lifted_from = lifted_from
    386         self.func_attr = func_attr
--> 387         return self._compile_bytecode()
    388 
    389     def compile_internal(self, bc, func_attr=DEFAULT_FUNCTION_ATTRIBUTES):

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in _compile_bytecode(self)
    669 
    670         pm.finalize()
--> 671         res = pm.run(self.status)
    672         if res is not None:
    673             # Early pipeline completion

/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py in run(self, status)
    255                     # No more fallback pipelines?
    256                     if is_final_pipeline:
--> 257                         raise patched_exception
    258                     # Go to next fallback pipeline
    259                     else:

LoweringError: Caused By:
Traceback (most recent call last):
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 249, in run
    stage()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 616, in stage_nopython_backend
    self._backend(lowerfn, objectmode=False)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 571, in _backend
    lowered = lowerfn()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 558, in backend_nopython_mode
    self.flags)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/compiler.py", line 816, in native_lowering_stage
    lower.lower()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 123, in lower
    self.lower_normal_function(self.fndesc)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 158, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 183, in lower_function_body
    self.lower_block(block)
  File "/Users/zzz/anaconda/envs/bisect_test/lib/python2.7/site-packages/numba/lowering.py", line 201, in lower_block
    raise LoweringError(msg, inst.loc)
LoweringError: Internal error:
NotImplementedError: ?int64 as constant unsupported
File "<ipython-input-1-8b4f39ee75a4>", line 6

Failed at nopython (nopython mode backend)
Internal error:
NotImplementedError: ?int64 as constant unsupported
File "<ipython-input-1-8b4f39ee75a4>", line 6
```

The code also fails with numba 0.24.0 as well as the latest dev build (0.26.0.dev-np110py27_128)



Discussion:
@sklam: Can you take a look at this?

@sklam: Can you take a look at this?


Resolving patch:
diff --git a/numba/lowering.py b/numba/lowering.py
--- a/numba/lowering.py
+++ b/numba/lowering.py
@@ -392,8 +392,12 @@ def lower_assign(self, ty, inst):
             argty = self.typeof("arg." + value.name)
             if isinstance(argty, types.Omitted):
                 pyval = argty.value
-                res = self.context.get_constant_generic(self.builder, ty,
-                                                        pyval)
+                # use the type of the constant value
+                valty = self.context.typing_context.resolve_value_type(pyval)
+                const = self.context.get_constant_generic(self.builder, valty,
+                                                          pyval)
+                # cast it to the variable type
+                res = self.context.cast(self.builder, const, valty, ty)
             else:
                 val = self.fnargs[value.index]
                 res = self.context.cast(self.builder, val, argty, ty)
diff --git a/numba/targets/optional.py b/numba/targets/optional.py
--- a/numba/targets/optional.py
+++ b/numba/targets/optional.py
@@ -41,6 +41,10 @@ def optional_is_none(context, builder, sig, args):
 lower_builtin('is', types.Optional, types.none)(optional_is_none)
 lower_builtin('is', types.none, types.Optional)(optional_is_none)
 
+# Comparing none type to any other types result in False
+lower_builtin('is', types.none, types.Any)(always_return_false_impl)
+lower_builtin('is', types.Any, types.none)(always_return_false_impl)
+
 
 @lower_getattr_generic(types.Optional)
 def optional_getattr(context, builder, typ, value, attr):


Test patch:
diff --git a/numba/tests/test_optional.py b/numba/tests/test_optional.py
--- a/numba/tests/test_optional.py
+++ b/numba/tests/test_optional.py
@@ -200,6 +200,20 @@ def foo(val, run_second):
         self.assertIsNone(foo(123, False))
         self.assertEqual(foo(231, True), 231)
 
+    def test_optional_thru_omitted_arg(self):
+        """
+        Issue 1868
+        """
+
+        def pyfunc(x=None):
+            if x is None:
+                x = 1
+            return x
+
+        cfunc = njit(pyfunc)
+        self.assertEqual(pyfunc(), cfunc())
+        self.assertEqual(pyfunc(3), cfunc(3))
+
 
 if __name__ == '__main__':
     unittest.main()