Repository: numba/numba

Issue:
Incorrect number of arguments passed to numba jitted function
Found this while experimenting with tuples in numba:

``` python
In [36]: @nb.jit
def foo(a):
    return a[0] + a[1]
   ....:

In [37]: @nb.jit(nopython=True)
def bar(a, b):
    return a + b
   ....:

In [38]: def baz(x, y):
    return foo(x) + bar(*y)
   ....:

In [39]: baz2 = nb.jit(baz)

In [40]: data = (1, 1.0)

In [41]: foo(data)
Out[41]: 2.0

In [42]: bar(*data)
Out[42]: 2.0

In [43]: baz(data, data)
Out[43]: 4.0

In [44]: baz2(data, data)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-44-5f8e8d0c25a9> in <module>()
----> 1 baz2(data, data)

TypeError: not enough arguments: expected 2, got 0
```



Discussion:
I cannot reproduce. Which Numba version is this?

``` python
In [1]: import numba as nb

In [2]: nb.__version__
Out[2]: '0.22.1'
```

I see, I can reproduce on 0.22.1 now. It is a bug in object mode.


Resolving patch:
diff --git a/numba/objmode.py b/numba/objmode.py
--- a/numba/objmode.py
+++ b/numba/objmode.py
@@ -217,17 +217,23 @@ def lower_expr(self, expr):
         elif expr.op == 'call':
             argvals = [self.loadvar(a.name) for a in expr.args]
             fn = self.loadvar(expr.func.name)
+            args = self.pyapi.tuple_pack(argvals)
+            if expr.vararg:
+                # Expand *args
+                new_args = self.pyapi.number_add(args,
+                                                 self.loadvar(expr.vararg.name))
+                self.decref(args)
+                args = new_args
             if not expr.kws:
-                # No keyword
-                ret = self.pyapi.call_function_objargs(fn, argvals)
+                # No named arguments
+                ret = self.pyapi.call(fn, args, None)
             else:
-                # Have Keywords
+                # Named arguments
                 keyvalues = [(k, self.loadvar(v.name)) for k, v in expr.kws]
-                args = self.pyapi.tuple_pack(argvals)
                 kws = self.pyapi.dict_pack(keyvalues)
                 ret = self.pyapi.call(fn, args, kws)
                 self.decref(kws)
-                self.decref(args)
+            self.decref(args)
             self.check_error(ret)
             return ret
         elif expr.op == 'getattr':


Test patch:
diff --git a/numba/tests/test_nested_calls.py b/numba/tests/test_nested_calls.py
--- a/numba/tests/test_nested_calls.py
+++ b/numba/tests/test_nested_calls.py
@@ -6,26 +6,26 @@
 from __future__ import print_function, division, absolute_import
 
 from numba import int32, int64
-from numba import njit
+from numba import jit
 from numba import unittest_support as unittest
 from .support import TestCase
 
 
-@njit
+@jit(nopython=True)
 def f_inner(a, b, c):
     return a, b, c
 
 def f(x, y, z):
     return f_inner(x, c=y, b=z)
 
-@njit
+@jit(nopython=True)
 def g_inner(a, b=2, c=3):
     return a, b, c
 
 def g(x, y, z):
     return g_inner(x, b=y), g_inner(a=z, c=x)
 
-@njit
+@jit(nopython=True)
 def star_inner(a=5, *b):
     return a, b
 
@@ -35,7 +35,7 @@ def star(x, y, z):
 def star_call(x, y, z):
     return star_inner(x, *y), star_inner(*z)
 
-@njit
+@jit(nopython=True)
 def argcast_inner(a, b):
     if b:
         # Here `a` is unified to int64 (from int32 originally)
@@ -48,20 +48,21 @@ def argcast(a, b):
 
 class TestNestedCall(TestCase):
 
-    def compile_func(self, pyfunc):
+    def compile_func(self, pyfunc, objmode=False):
         def check(*args, **kwargs):
             expected = pyfunc(*args, **kwargs)
             result = f(*args, **kwargs)
             self.assertPreciseEqual(result, expected)
-        f = njit(pyfunc)
+        flags = dict(forceobj=True) if objmode else dict(nopython=True)
+        f = jit(**flags)(pyfunc)
         return f, check
 
     def test_boolean_return(self):
-        @njit
+        @jit(nopython=True)
         def inner(x):
             return not x
 
-        @njit
+        @jit(nopython=True)
         def outer(x):
             if inner(x):
                 return True
@@ -71,22 +72,28 @@ def outer(x):
         self.assertFalse(outer(True))
         self.assertTrue(outer(False))
 
-    def test_named_args(self):
+    def test_named_args(self, objmode=False):
         """
         Test a nested function call with named (keyword) arguments.
         """
-        cfunc, check = self.compile_func(f)
+        cfunc, check = self.compile_func(f, objmode)
         check(1, 2, 3)
         check(1, y=2, z=3)
 
-    def test_default_args(self):
+    def test_named_args_objmode(self):
+        self.test_named_args(objmode=True)
+
+    def test_default_args(self, objmode=False):
         """
         Test a nested function call using default argument values.
         """
-        cfunc, check = self.compile_func(g)
+        cfunc, check = self.compile_func(g, objmode)
         check(1, 2, 3)
         check(1, y=2, z=3)
 
+    def test_default_args_objmode(self):
+        self.test_default_args(objmode=True)
+
     def test_star_args(self):
         """
         Test a nested function call to a function with *args in its signature.
@@ -94,13 +101,16 @@ def test_star_args(self):
         cfunc, check = self.compile_func(star)
         check(1, 2, 3)
 
-    def test_star_call(self):
+    def test_star_call(self, objmode=False):
         """
         Test a function call with a *args.
         """
-        cfunc, check = self.compile_func(star_call)
+        cfunc, check = self.compile_func(star_call, objmode)
         check(1, (2,), (3,))
 
+    def test_star_call_objmode(self):
+        self.test_star_call(objmode=True)
+
     def test_argcast(self):
         """
         Issue #1488: implicitly casting an argument variable should not