Repository: numba/numba

Issue:
Change in type promotion rules from numba 0.19->0.21 causes lowering error



Discussion:
If you run this code:

https://gist.github.com/talumbau/de3cfd88b507b6601bea

with numba 0.21 and set `intdtype` to `'int32'` on line 41 you get this error:

```
Traceback (most recent call last):
  File "try3.py", line 87, in <module>
    hl_func(pm, pf)
  File "try3.py", line 47, in hl_func
    ap_func(pf.c02650, pf.c00100, pf._agierr, pf._posagi, pf._ywossbe, pf._ywossbc, pf._prexmp, pf.c04600, pf._ymod1, pf.c02500, pf.c02700, pf.e02615, pf.c02900, pf.e00100, pf.e02500, pf.XTOT, pm.II_em, pm.II_em_ps, pf.MARS, pf._sep, pm.II_prt, pf.DSI, )
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/dispatcher.py", line 171, in _compile_for_args
    return self.compile(sig)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/dispatcher.py", line 348, in compile
    flags=flags, locals=self.locals)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 637, in compile_extra
    return pipeline.compile_extra(func)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 358, in compile_extra
    return self.compile_bytecode(bc, func_attr=self.func_attr)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 367, in compile_bytecode
    return self._compile_bytecode()
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 624, in _compile_bytecode
    return pm.run(self.status)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 250, in run
    raise patched_exception
numba.errors.LoweringError: Caused By:
Traceback (most recent call last):
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 242, in run
    res = stage()
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 580, in stage_nopython_backend
    return self._backend(lowerfn, objectmode=False)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 533, in _backend
    lowered = lowerfn()
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 524, in backend_nopython_mode
    self.flags)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/compiler.py", line 766, in native_lowering_stage
    lower.lower()
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/lowering.py", line 123, in lower
    self.lower_normal_function(self.fndesc)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/lowering.py", line 158, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/lowering.py", line 183, in lower_function_body
    self.lower_block(block)
  File "/Users/talumbau/miniconda3/envs/heroku_aei/lib/python2.7/site-packages/numba/lowering.py", line 201, in lower_block
    raise LoweringError(msg, inst.loc)
LoweringError: Internal error:
NotImplementedError: No definition for lowering <class 'numba.types.Dispatcher'>(float64, float64, float64, float64, float64, int32, int32, int32, int64, array(int64, 1d, C), int32, float64, float64, int32) -> (float64, float64, float64, float64, int64, float64, int64, float64)
File "try3.py", line 38

Failed at nopython (nopython mode backend)
Internal error:
NotImplementedError: No definition for lowering <class 'numba.types.Dispatcher'>(float64, float64, float64, float64, float64, int32, int32, int32, int64, array(int64, 1d, C), int32, float64, float64, int32) -> (float64, float64, float64, float64, int64, float64, int64, float64)
File "try3.py", line 38
```

But it runs successfully with `intdtype = 'int64'`. With numba version 0.19, it run successfully when `intdtype` is either `'int32'` or `'int64'`. So, the question is:
- should it run successfully with either integer type, in which case numba 0.19 is more correct than 0.21, or is it correct to raise the error in 0.21 of numba, and if so, is that the best error exception to raise?

@pitrou: Can you take a look at this?


Resolving patch:
diff --git a/numba/funcdesc.py b/numba/funcdesc.py
--- a/numba/funcdesc.py
+++ b/numba/funcdesc.py
@@ -60,7 +60,12 @@ def __init__(self, native, modname, qualname, unique_name, doc,
         self.kws = kws
         self.restype = restype
         # Argument types
-        self.argtypes = argtypes or [self.typemap[a] for a in args]
+        if argtypes is not None:
+            self.argtypes = argtypes
+        else:
+            # Get argument types from the type inference result
+            # (note the "arg.FOO" convention as used in typeinfer
+            self.argtypes = [self.typemap['arg.' + a] for a in args]
         mangler = default_mangler if mangler is None else mangler
         # The mangled name *must* be unique, else the wrong function can
         # be chosen at link time.
diff --git a/numba/lowering.py b/numba/lowering.py
--- a/numba/lowering.py
+++ b/numba/lowering.py
@@ -402,7 +402,11 @@ def lower_assign(self, ty, inst):
             return res
 
         elif isinstance(value, ir.Arg):
-            res = self.fnargs[value.index]
+            val = self.fnargs[value.index]
+            # Cast from the argument type to the local variable type
+            # (note the "arg.FOO" convention as used in typeinfer)
+            oty = self.typeof("arg." + value.name)
+            res = self.context.cast(self.builder, val, oty, ty)
             self.incref(ty, res)
             return res
 


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
@@ -5,6 +5,7 @@
 
 from __future__ import print_function, division, absolute_import
 
+from numba import int32, int64
 from numba import njit
 from numba import unittest_support as unittest
 from .support import TestCase
@@ -34,6 +35,16 @@ def star(x, y, z):
 def star_call(x, y, z):
     return star_inner(x, *y), star_inner(*z)
 
+@njit
+def argcast_inner(a, b):
+    if b:
+        # Here `a` is unified to int64 (from int32 originally)
+        a = int64(0)
+    return a
+
+def argcast(a, b):
+    return argcast_inner(int32(a), b)
+
 
 class TestNestedCall(TestCase):
 
@@ -90,6 +101,15 @@ def test_star_call(self):
         cfunc, check = self.compile_func(star_call)
         check(1, (2,), (3,))
 
+    def test_argcast(self):
+        """
+        Issue #1488: implicitly casting an argument variable should not
+        break nested calls.
+        """
+        cfunc, check = self.compile_func(argcast)
+        check(1, 0)
+        check(1, 1)
+
 
 if __name__ == '__main__':
     unittest.main()