# Buggy code
def unify(self):
    """
    Run the final unification pass over all inferred types, and
    catch imprecise types.
    """
    typdict = utils.UniqueDict()

    def find_offender(name, exhaustive=False):
        # finds the offending variable definition by name
        # if exhaustive is set it will try and trace through temporary
        # variables to find a concrete offending definition.
        offender = None
        for block in self.func_ir.blocks.values():
            offender = block.find_variable_assignment(name)
            if offender is not None:
                if not exhaustive:
                    break
                try:  # simple assignment
                    hasattr(offender.value, "name")
                    offender_value = offender.value.name
                except (AttributeError, KeyError):
                    break
                orig_offender = offender
                if offender_value.startswith("$"):
                    offender = find_offender(offender_value, exhaustive=exhaustive)
                    if offender is None:
                        offender = orig_offender
                break
        return offender

    def diagnose_imprecision(offender):
        # helper for diagnosing imprecise types

        list_msg = """\n
For Numba to be able to compile a list, the list must have a known and
precise type that can be inferred from the other variables. Whilst sometimes
the type of empty lists can be inferred, this is not always the case, see this
documentation for help:

http://numba.pydata.org/numba-doc/latest/user/troubleshoot.html#my-code-has-an-untyped-list-problem
"""
        if offender is not None:
            # This block deals with imprecise lists
            if hasattr(offender, "value"):
                if hasattr(offender.value, "op"):
                    # might be `foo = []`
                    if offender.value.op == "build_list":
                        return list_msg
                    # or might be `foo = list()`
                    elif offender.value.op == "call":
                        try:  # assignment involving a call
                            call_name = offender.value.func.name
                            # find the offender based on the call name
                            offender = find_offender(call_name)
                            if isinstance(offender.value, ir.Global):
                                if offender.value.name == "list":
                                    return list_msg
                        except (AttributeError, KeyError):
                            pass
        return ""  # no help possible

    def check_var(name):
        tv = self.typevars[name]
        if not tv.defined:
            offender = find_offender(name)
            val = getattr(offender, "value", "unknown operation")
            loc = getattr(offender, "loc", ir.unknown_loc)
            msg = (
                "Type of variable '%s' cannot be determined, operation:"
                " %s, location: %s"
            )
            raise TypingError(msg % (var, val, loc), loc)
        tp = tv.getone()
        if not tp.is_precise():
            offender = find_offender(name, exhaustive=True)
            msg = (
                "Cannot infer the type of variable '%s'%s, have imprecise type: %s. %s"
            )
            istmp = " (temporary variable)" if var.startswith("$") else ""
            loc = getattr(offender, "loc", ir.unknown_loc)
            # is this an untyped list? try and provide help
            extra_msg = diagnose_imprecision(offender)
            raise TypingError(msg % (var, istmp, tp, extra_msg), loc)
        else:  # type is precise, hold it
            typdict[var] = tp

    # For better error display, check first user-visible vars, then
    # temporaries
    temps = set(k for k in self.typevars if not k[0].isalpha())
    others = set(self.typevars) - temps
    for var in sorted(others):
        check_var(var)
    for var in sorted(temps):
        check_var(var)

    retty = self.get_return_type(typdict)
    fntys = self.get_function_types(typdict)
    if self.generator_info:
        retty = self.get_generator_type(typdict, retty)

    self.debug.unify_finished(typdict, retty, fntys)

    return typdict, retty, fntys


# Traceback (IndexError)
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)

# Fixed code
def unify(self, raise_errors=True):
    """
    Run the final unification pass over all inferred types, and
    catch imprecise types.
    """
    typdict = utils.UniqueDict()

    def find_offender(name, exhaustive=False):
        # finds the offending variable definition by name
        # if exhaustive is set it will try and trace through temporary
        # variables to find a concrete offending definition.
        offender = None
        for block in self.func_ir.blocks.values():
            offender = block.find_variable_assignment(name)
            if offender is not None:
                if not exhaustive:
                    break
                try:  # simple assignment
                    hasattr(offender.value, "name")
                    offender_value = offender.value.name
                except (AttributeError, KeyError):
                    break
                orig_offender = offender
                if offender_value.startswith("$"):
                    offender = find_offender(offender_value, exhaustive=exhaustive)
                    if offender is None:
                        offender = orig_offender
                break
        return offender

    def diagnose_imprecision(offender):
        # helper for diagnosing imprecise types

        list_msg = """\n
For Numba to be able to compile a list, the list must have a known and
precise type that can be inferred from the other variables. Whilst sometimes
the type of empty lists can be inferred, this is not always the case, see this
documentation for help:

http://numba.pydata.org/numba-doc/latest/user/troubleshoot.html#my-code-has-an-untyped-list-problem
"""
        if offender is not None:
            # This block deals with imprecise lists
            if hasattr(offender, "value"):
                if hasattr(offender.value, "op"):
                    # might be `foo = []`
                    if offender.value.op == "build_list":
                        return list_msg
                    # or might be `foo = list()`
                    elif offender.value.op == "call":
                        try:  # assignment involving a call
                            call_name = offender.value.func.name
                            # find the offender based on the call name
                            offender = find_offender(call_name)
                            if isinstance(offender.value, ir.Global):
                                if offender.value.name == "list":
                                    return list_msg
                        except (AttributeError, KeyError):
                            pass
        return ""  # no help possible

    def check_var(name):
        tv = self.typevars[name]
        if not tv.defined:
            if raise_errors:
                offender = find_offender(name)
                val = getattr(offender, "value", "unknown operation")
                loc = getattr(offender, "loc", ir.unknown_loc)
                msg = (
                    "Type of variable '%s' cannot be determined, "
                    "operation: %s, location: %s"
                )
                raise TypingError(msg % (var, val, loc), loc)
            else:
                typdict[var] = types.unknown
                return
        tp = tv.getone()
        if not tp.is_precise():
            offender = find_offender(name, exhaustive=True)
            msg = (
                "Cannot infer the type of variable '%s'%s, have imprecise type: %s. %s"
            )
            istmp = " (temporary variable)" if var.startswith("$") else ""
            loc = getattr(offender, "loc", ir.unknown_loc)
            # is this an untyped list? try and provide help
            extra_msg = diagnose_imprecision(offender)
            if raise_errors:
                raise TypingError(msg % (var, istmp, tp, extra_msg), loc)
            else:
                typdict[var] = types.unknown
                return
        else:  # type is precise, hold it
            typdict[var] = tp

    # For better error display, check first user-visible vars, then
    # temporaries
    temps = set(k for k in self.typevars if not k[0].isalpha())
    others = set(self.typevars) - temps
    for var in sorted(others):
        check_var(var)
    for var in sorted(temps):
        check_var(var)

    try:
        retty = self.get_return_type(typdict)
    except Exception as e:
        # partial type inference may raise e.g. attribute error if a
        # constraint has no computable signature, ignore this as needed
        if raise_errors:
            raise e
        else:
            retty = None

    try:
        fntys = self.get_function_types(typdict)
    except Exception as e:
        # partial type inference may raise e.g. attribute error if a
        # constraint has no computable signature, ignore this as needed
        if raise_errors:
            raise e
        else:
            fntys = None

    if self.generator_info:
        retty = self.get_generator_type(typdict, retty, raise_errors=raise_errors)

    self.debug.unify_finished(typdict, retty, fntys)

    return typdict, retty, fntys