Repository: numba/numba

Issue:
Boolean Type Inference
Numba seems to choke on functions of booleans (some kind of automatic casting to int?).

A minimal test case:

``` Python
In [1]: import numba
In [2]: numba.__version__
Out[2]: '0.18.2'

In [4]: @numba.jit(nopython=True)
def if_then(a, b):
    if not a:
        return True
    return b
   ...: 

In [5]: if_then(True, False)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-5-e25b1139e4f3> in <module>()
----> 1 f(True, False)

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/dispatcher.py in _compile_for_args(self, *args, **kws)
    160         assert not kws
    161         sig = tuple([self.typeof_pyval(a) for a in args])
--> 162         return self.compile(sig)
    163 
    164     def inspect_llvm(self, signature=None):

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/dispatcher.py in compile(self, sig)
    303                                           self.py_func,
    304                                           args=args, return_type=return_type,
--> 305                                           flags=flags, locals=self.locals)
    306 
    307             # Check typing error if object mode is used

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library)
    561     pipeline = Pipeline(typingctx, targetctx, library,
    562                         args, return_type, flags, locals)
--> 563     return pipeline.compile_extra(func)
    564 
    565 

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in compile_extra(self, func)
    299                 raise e
    300 
--> 301         return self.compile_bytecode(bc, func_attr=self.func_attr)
    302 
    303     def compile_bytecode(self, bc, lifted=(), lifted_from=None,

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in compile_bytecode(self, bc, lifted, lifted_from, func_attr)
    308         self.lifted_from = lifted_from
    309         self.func_attr = func_attr
--> 310         return self._compile_bytecode()
    311 
    312     def compile_internal(self, bc, func_attr=DEFAULT_FUNCTION_ATTRIBUTES):

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in _compile_bytecode(self)
    548 
    549         pm.finalize()
--> 550         return pm.run(self.status)
    551 
    552 

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in run(self, status)
    197                     # No more fallback pipelines?
    198                     if is_final_pipeline:
--> 199                         raise patched_exception
    200                     # Go to next fallback pipeline
    201                     else:

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in run(self, status)
    189             for stage, stage_name in self.pipeline_stages[pipeline_name]:
    190                 try:
--> 191                     res = stage()
    192                 except _EarlyPipelineCompletion as e:
    193                     return e.result

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in stage_nopython_frontend(self)
    396                 self.args,
    397                 self.return_type,
--> 398                 self.locals)
    399 
    400         with self.fallback_context('Function "%s" has invalid return type'

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/compiler.py in type_inference_stage(typingctx, interp, args, return_type, locals)
    685     infer.build_constrain()
    686     infer.propagate()
--> 687     typemap, restype, calltypes = infer.unify()
    688 
    689     if config.DEBUG:

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/typeinfer.py in unify(self)
    412                 raise TypingError("Var '%s' unified to object: %s" % (var, tv))
    413             typdict[var] = unified
--> 414         retty = self.get_return_type(typdict)
    415         fntys = self.get_function_types(typdict)
    416         if self.generator_info:

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/typeinfer.py in get_return_type(self, typemap)
    489                 return types.none
    490         elif rettypes:
--> 491             unified = self.context.unify_types(*rettypes)
    492             return unified
    493         else:

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/typing/context.py in unify_types(self, *typelist)
    356 
    357         return functools.reduce(
--> 358             self.unify_pairs, sorted(typelist, key=keyfunc))
    359 
    360     def unify_pairs(self, first, second):

/home/alan/anaconda/envs/test/lib/python3.4/site-packages/numba/typing/context.py in unify_pairs(self, first, second)
    403                "{first}->{second}::{forward}\n"
    404                "{second}->{first}::{backward} ")
--> 405         raise AssertionError(msg.format(**locals()))
    406 
    407 

AssertionError: Failed at nopython (nopython frontend)
Cannot unify {bool, int64}
bool->int64::safe
int64->bool::unsafe 

```



Discussion:

Resolving patch:
diff --git a/numba/dispatcher.py b/numba/dispatcher.py
--- a/numba/dispatcher.py
+++ b/numba/dispatcher.py
@@ -208,11 +208,6 @@ def typeof_pyval(self, val):
         This is called from numba._dispatcher as a fallback if the native code
         cannot decide the type.
         """
-        if isinstance(val, utils.INT_TYPES):
-            # Ensure no autoscaling of integer type, to match the
-            # typecode() function in _dispatcher.c.
-            return types.int64
-
         tp = self.typingctx.resolve_argument_type(val)
         if tp is None:
             tp = types.pyobject
diff --git a/numba/typing/context.py b/numba/typing/context.py
--- a/numba/typing/context.py
+++ b/numba/typing/context.py
@@ -127,8 +127,8 @@ def resolve_argument_type(self, val):
 
         Unknown types will be mapped to pyobject.
         """
-        if isinstance(val, utils.INT_TYPES):
-            # Force all integers to be 64-bit
+        # Force all integers (except bools) to be 64-bit
+        if isinstance(val, utils.INT_TYPES) and not isinstance(val, bool):
             return types.int64
 
         tp = self.resolve_data_type(val)


Test patch:
diff --git a/numba/tests/test_typeinfer.py b/numba/tests/test_typeinfer.py
--- a/numba/tests/test_typeinfer.py
+++ b/numba/tests/test_typeinfer.py
@@ -170,7 +170,13 @@ def issue_797(x0, y0, x1, y1, grid):
             y0 += sy
 
 
-class TestIssue(object):
+def issue_1080(a, b):
+    if not a:
+        return True
+    return b
+
+
+class TestIssue(unittest.TestCase):
     def test_issue_797(self):
         """https://github.com/numba/numba/issues/797#issuecomment-58592401
 
@@ -180,6 +186,14 @@ def test_issue_797(self):
         g = np.zeros(shape=(10, 10), dtype=np.int32)
         foo(np.int32(0), np.int32(0), np.int32(1), np.int32(1), g)
 
+    def test_issue_1080(self):
+        """https://github.com/numba/numba/issues/1080
+
+        Erroneous promotion of boolean args to int64
+        """
+        foo = jit(nopython=True)(issue_1080)
+        foo(True, False)
+
 
 class TestCoercion(unittest.TestCase):
     """