Repository: numba/numba

Issue:
master: @overload_method issues with *args
<!--

Thanks for opening an issue! To help the Numba team handle your information
efficiently, please first ensure that there is no other issue present that
already describes the issue you have
(search at https://github.com/numba/numba/issues?&q=is%3Aissue).

For more general "how do I do X?" type questions, please speak to us in real
time on https://gitter.im/numba/numba or post to the Numba mailing list
https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

-->

## Reporting a bug

<!--

Before submitting a bug report please ensure that you can check off these boxes:

-->

- [ ] 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).

<!--

Please include details of the bug here, including, if applicable, what you
expected to happen!

-->

Seems to happens after `@overload_method` refactoring merge
```
class DummyType(types.Opaque):
    pass

dummy_type = DummyType("my_dummy")
register_model(DummyType)(OpaqueModel)

class Dummy(object):
    pass

@typeof_impl.register(Dummy)
def typeof_Dummy(val, c):
    return dummy_type

@unbox(DummyType)
def unbox_index(typ, obj, c):
    return NativeValue(c.context.get_dummy_value())

@overload_method(DummyType, "inline_method")
def _get_inlined_method(obj,val,val2,*args):
    def get(obj, val, val2,*args):
        return ("THIS IS INLINED", val, val2)
    return get

@njit
def bar(obj):
    return obj.inline_method(123,456)

print(bar(Dummy()))
```
```
Traceback (most recent call last):
  File "/home/ibutygin/miniconda3/envs/NUMBA_CUSTOM/lib/python3.7/site-packages/llvmlite/ir/instructions.py", line 619, in __init__
    typ = typ.elements[i]
IndexError: tuple index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ibutygin/src/numba/numba/numba/errors.py", line 717, in new_error_context
    yield
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 260, in lower_block
    self.lower_inst(inst)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 303, in lower_inst
    val = self.lower_assign(ty, inst)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 467, in lower_assign
    return self.lower_expr(ty, value)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 932, in lower_expr
    res = self.lower_call(resty, expr)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 724, in lower_call
    res = self._lower_call_normal(fnty, expr, signature)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 903, in _lower_call_normal
    res = impl(self.builder, argvals, self.loc)
  File "/home/ibutygin/src/numba/numba/numba/targets/base.py", line 1132, in __call__
    res = self._imp(self._context, builder, self._sig, args, loc=loc)
  File "/home/ibutygin/src/numba/numba/numba/targets/base.py", line 1157, in wrapper
    return fn(*args, **kwargs)
  File "/home/ibutygin/src/numba/numba/numba/typing/templates.py", line 778, in method_impl
    return call(builder, args)
  File "/home/ibutygin/src/numba/numba/numba/targets/base.py", line 1132, in __call__
    res = self._imp(self._context, builder, self._sig, args, loc=loc)
  File "/home/ibutygin/src/numba/numba/numba/targets/base.py", line 1157, in wrapper
    return fn(*args, **kwargs)
  File "/home/ibutygin/src/numba/numba/numba/targets/imputils.py", line 193, in imp
    builder, func, fndesc.restype, fndesc.argtypes, args)
  File "/home/ibutygin/src/numba/numba/numba/targets/callconv.py", line 477, in call_function
    args = list(arginfo.as_arguments(builder, args))
  File "/home/ibutygin/src/numba/numba/numba/datamodel/packer.py", line 100, in as_arguments
    for dm, val in zip(self._dm_args, values)
  File "/home/ibutygin/src/numba/numba/numba/datamodel/packer.py", line 100, in <listcomp>
    for dm, val in zip(self._dm_args, values)
  File "/home/ibutygin/src/numba/numba/numba/datamodel/models.py", line 447, in as_argument
    v = builder.extract_value(value, [i])
  File "/home/ibutygin/miniconda3/envs/NUMBA_CUSTOM/lib/python3.7/site-packages/llvmlite/ir/builder.py", line 927, in extract_value
    instr = instructions.ExtractValue(self.block, agg, idx, name=name)
  File "/home/ibutygin/miniconda3/envs/NUMBA_CUSTOM/lib/python3.7/site-packages/llvmlite/ir/instructions.py", line 622, in __init__
    % (list(indices), agg.type))
TypeError: Can't index at [0] in {}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 73, in <module>
    print(bar(Dummy()))
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 420, in _compile_for_args
    raise e
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 353, in _compile_for_args
    return self.compile(tuple(argtypes))
  File "/home/ibutygin/src/numba/numba/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 768, in compile
    cres = self._compiler.compile(args, return_type)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 77, in compile
    status, retval = self._compile_cached(args, return_type)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 91, in _compile_cached
    retval = self._compile_core(args, return_type)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 109, in _compile_core
    pipeline_class=self.pipeline_class)
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 543, in compile_extra
    return pipeline.compile_extra(func)
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 328, in compile_extra
    return self._compile_bytecode()
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 389, in _compile_bytecode
    return self._compile_core()
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 368, in _compile_core
    raise e
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 359, in _compile_core
    pm.run(self.state)
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 331, in run
    raise patched_exception
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 322, in run
    self._runPass(idx, pass_inst, state)
  File "/home/ibutygin/src/numba/numba/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 281, in _runPass
    mutated |= check(pss.run_pass, internal_state)
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 268, in check
    mangled = func(compiler_state)
  File "/home/ibutygin/src/numba/numba/numba/typed_passes.py", line 391, in run_pass
    NativeLowering().run_pass(state)
  File "/home/ibutygin/src/numba/numba/numba/typed_passes.py", line 333, in run_pass
    lower.lower()
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 179, in lower
    self.lower_normal_function(self.fndesc)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 220, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 245, in lower_function_body
    self.lower_block(block)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 260, in lower_block
    self.lower_inst(inst)
  File "/home/ibutygin/miniconda3/envs/NUMBA_CUSTOM/lib/python3.7/contextlib.py", line 130, in __exit__
    self.gen.throw(type, value, traceback)
  File "/home/ibutygin/src/numba/numba/numba/errors.py", line 725, in new_error_context
    six.reraise(type(newerr), newerr, tb)
  File "/home/ibutygin/src/numba/numba/numba/six.py", line 669, in reraise
    raise value
numba.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
Can't index at [0] in {}

File "test.py", line 71:
def bar(obj):
    return obj.inline_method(123,456)
    ^

[1] During: lowering "$10call_method.4 = call $4load_method.1($const6.2, $const8.3, func=$4load_method.1, args=[Var($const6.2, test.py:71), Var($const8.3, test.py:71)], kws=(), vararg=None)" at test.py (71)
```
If I write
```
@overload_method(DummyType, "inline_method", strict=False)
def _get_inlined_method(obj,val,val2,*args):
    def get(obj, val, val2):
        return ("THIS IS INLINED", val, val2)
    return get
```
```
Traceback (most recent call last):
  File "/home/ibutygin/src/numba/numba/numba/errors.py", line 717, in new_error_context
    yield
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 260, in lower_block
    self.lower_inst(inst)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 303, in lower_inst
    val = self.lower_assign(ty, inst)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 467, in lower_assign
    return self.lower_expr(ty, value)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 932, in lower_expr
    res = self.lower_call(resty, expr)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 724, in lower_call
    res = self._lower_call_normal(fnty, expr, signature)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 893, in _lower_call_normal
    fnty, signature, expr.args, expr.vararg, expr.kws,
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 667, in fold_call_args
    stararg_handler)
  File "/home/ibutygin/src/numba/numba/numba/typing/templates.py", line 179, in fold_arguments
    ba.arguments.get(name, ()))
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 657, in stararg_handler
    stararg_ty = signature.args[index]
IndexError: tuple index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 73, in <module>
    print(bar(Dummy()))
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 420, in _compile_for_args
    raise e
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 353, in _compile_for_args
    return self.compile(tuple(argtypes))
  File "/home/ibutygin/src/numba/numba/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 768, in compile
    cres = self._compiler.compile(args, return_type)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 77, in compile
    status, retval = self._compile_cached(args, return_type)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 91, in _compile_cached
    retval = self._compile_core(args, return_type)
  File "/home/ibutygin/src/numba/numba/numba/dispatcher.py", line 109, in _compile_core
    pipeline_class=self.pipeline_class)
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 543, in compile_extra
    return pipeline.compile_extra(func)
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 328, in compile_extra
    return self._compile_bytecode()
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 389, in _compile_bytecode
    return self._compile_core()
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 368, in _compile_core
    raise e
  File "/home/ibutygin/src/numba/numba/numba/compiler.py", line 359, in _compile_core
    pm.run(self.state)
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 331, in run
    raise patched_exception
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 322, in run
    self._runPass(idx, pass_inst, state)
  File "/home/ibutygin/src/numba/numba/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 281, in _runPass
    mutated |= check(pss.run_pass, internal_state)
  File "/home/ibutygin/src/numba/numba/numba/compiler_machinery.py", line 268, in check
    mangled = func(compiler_state)
  File "/home/ibutygin/src/numba/numba/numba/typed_passes.py", line 391, in run_pass
    NativeLowering().run_pass(state)
  File "/home/ibutygin/src/numba/numba/numba/typed_passes.py", line 333, in run_pass
    lower.lower()
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 179, in lower
    self.lower_normal_function(self.fndesc)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 220, in lower_normal_function
    entry_block_tail = self.lower_function_body()
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 245, in lower_function_body
    self.lower_block(block)
  File "/home/ibutygin/src/numba/numba/numba/lowering.py", line 260, in lower_block
    self.lower_inst(inst)
  File "/home/ibutygin/miniconda3/envs/NUMBA_CUSTOM/lib/python3.7/contextlib.py", line 130, in __exit__
    self.gen.throw(type, value, traceback)
  File "/home/ibutygin/src/numba/numba/numba/errors.py", line 725, in new_error_context
    six.reraise(type(newerr), newerr, tb)
  File "/home/ibutygin/src/numba/numba/numba/six.py", line 669, in reraise
    raise value
numba.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
tuple index out of range

File "test.py", line 71:
def bar(obj):
    return obj.inline_method(123,456)
    ^

[1] During: lowering "$10call_method.4 = call $4load_method.1($const6.2, $const8.3, func=$4load_method.1, args=[Var($const6.2, test.py:71), Var($const8.3, test.py:71)], kws=(), vararg=None)" at test.py (71)
```

Second variant worked fine previously


Discussion:

Resolving patch:
diff --git a/numba/dictobject.py b/numba/dictobject.py
--- a/numba/dictobject.py
+++ b/numba/dictobject.py
@@ -74,14 +74,15 @@ class Status(IntEnum):
 
 
 def new_dict(key, value):
-    """Construct a new dict. (Not implemented in the interpreter yet)
+    """Construct a new dict.
 
     Parameters
     ----------
     key, value : TypeRef
         Key type and value type of the new dict.
     """
-    raise NotImplementedError
+    # With JIT disabled, ignore all arguments and return a Python dict.
+    return dict()
 
 
 @register_model(DictType)
diff --git a/numba/typed/typeddict.py b/numba/typed/typeddict.py
--- a/numba/typed/typeddict.py
+++ b/numba/typed/typeddict.py
@@ -1,6 +1,7 @@
 """
 Python wrapper that connects CPython interpreter to the numba dictobject.
 """
+from numba import config
 from numba.six import MutableMapping
 from numba.types import DictType, TypeRef
 from numba.targets.imputils import numba_typeref_ctor
@@ -80,12 +81,22 @@ class Dict(MutableMapping):
 
     Implements the MutableMapping interface.
     """
+
+    def __new__(cls, dcttype=None, meminfo=None):
+        if config.DISABLE_JIT:
+            return dict.__new__(dict)
+        else:
+            return object.__new__(cls)
+
     @classmethod
     def empty(cls, key_type, value_type):
         """Create a new empty Dict with *key_type* and *value_type*
         as the types for the keys and values of the dictionary respectively.
         """
-        return cls(dcttype=DictType(key_type, value_type))
+        if config.DISABLE_JIT:
+            return dict()
+        else:
+            return cls(dcttype=DictType(key_type, value_type))
 
     def __init__(self, **kwargs):
         """


Test patch:
diff --git a/numba/tests/test_dictobject.py b/numba/tests/test_dictobject.py
--- a/numba/tests/test_dictobject.py
+++ b/numba/tests/test_dictobject.py
@@ -19,7 +19,8 @@
 from numba.typedobjectutils import _sentry_safe_cast
 from numba.utils import IS_PY3
 from numba.errors import TypingError
-from .support import TestCase, MemoryLeakMixin, unittest
+from .support import (TestCase, MemoryLeakMixin, unittest, override_config,
+                      forbid_codegen)
 
 skip_py2 = unittest.skipUnless(IS_PY3, reason='not supported in py2')
 
@@ -1585,3 +1586,25 @@ def foo(x):
         d = foo(Bag(a=100))
         self.assertEqual(d[0].a, 100)
         self.assertEqual(d[1].a, 101)
+
+
+class TestNoJit(TestCase):
+    """Exercise dictionary creation with JIT disabled. """
+
+    def test_dict_create_no_jit_using_new_dict(self):
+        with override_config('DISABLE_JIT', True):
+            with forbid_codegen():
+                d = dictobject.new_dict(int32, float32)
+                self.assertEqual(type(d), dict)
+
+    def test_dict_create_no_jit_using_Dict(self):
+        with override_config('DISABLE_JIT', True):
+            with forbid_codegen():
+                d = Dict()
+                self.assertEqual(type(d), dict)
+
+    def test_dict_create_no_jit_using_empty(self):
+        with override_config('DISABLE_JIT', True):
+            with forbid_codegen():
+                d = Dict.empty(types.int32, types.float32)
+                self.assertEqual(type(d), dict)