# Buggy code
def _analyze_inst(self, label, scope, equiv_set, inst, redefined):
    pre = []
    post = []
    if isinstance(inst, ir.Assign):
        lhs = inst.target
        typ = self.typemap[lhs.name]
        shape = None
        if isinstance(typ, types.ArrayCompatible) and typ.ndim == 0:
            shape = ()
        elif isinstance(inst.value, ir.Expr):
            result = self._analyze_expr(scope, equiv_set, inst.value)
            if result:
                shape = result[0]
                pre = result[1]
                if len(result) > 2:
                    rhs = result[2]
                    inst.value = rhs
        elif isinstance(inst.value, ir.Var) or isinstance(inst.value, ir.Const):
            shape = inst.value

        if isinstance(shape, ir.Const):
            if isinstance(shape.value, tuple):
                loc = shape.loc
                shape = tuple(ir.Const(x, loc) for x in shape.value)
            elif isinstance(shape.value, int):
                shape = (shape,)
            else:
                shape = None
        elif isinstance(shape, ir.Var) and isinstance(
            self.typemap[shape.name], types.Integer
        ):
            shape = (shape,)
        elif isinstance(shape, WrapIndexMeta):
            """ Here we've got the special WrapIndexMeta object
                    back from analyzing a wrap_index call.  We define
                    the lhs and then get it's equivalence class then
                    add the mapping from the tuple of slice size and
                    dimensional size equivalence ids to the lhs
                    equivalence id.
                """
            equiv_set.define(lhs, redefined, self.func_ir, typ)
            lhs_ind = equiv_set._get_ind(lhs.name)
            if lhs_ind != -1:
                equiv_set.wrap_map[(shape.slice_size, shape.dim_size)] = lhs_ind
            return pre, post

        if isinstance(typ, types.ArrayCompatible):
            if (
                shape == None
                or isinstance(shape, tuple)
                or (isinstance(shape, ir.Var) and not equiv_set.has_shape(shape))
            ):
                (shape, post) = self._gen_shape_call(equiv_set, lhs, typ.ndim, shape)
        elif isinstance(typ, types.UniTuple):
            if shape and isinstance(typ.dtype, types.Integer):
                (shape, post) = self._gen_shape_call(equiv_set, lhs, len(typ), shape)

        if shape != None:
            equiv_set.insert_equiv(lhs, shape)
        equiv_set.define(lhs, redefined, self.func_ir, typ)
    elif isinstance(inst, ir.StaticSetItem) or isinstance(inst, ir.SetItem):
        index = inst.index if isinstance(inst, ir.SetItem) else inst.index_var
        result = guard(self._index_to_shape, scope, equiv_set, inst.target, index)
        if not result:
            return [], []
        if result[0] is not None:
            inst.index_var = result[0]
        result = result[1]
        (target_shape, pre) = result
        value_shape = equiv_set.get_shape(inst.value)
        if value_shape == ():  # constant
            equiv_set.set_shape_setitem(inst, target_shape)
            return pre, []
        elif value_shape != None:
            target_typ = self.typemap[inst.target.name]
            require(isinstance(target_typ, types.ArrayCompatible))
            target_ndim = target_typ.ndim
            shapes = [target_shape, value_shape]
            names = [inst.target.name, inst.value.name]
            shape, asserts = self._broadcast_assert_shapes(
                scope, equiv_set, inst.loc, shapes, names
            )
            n = len(shape)
            # shape dimension must be within target dimension
            assert target_ndim >= n
            equiv_set.set_shape_setitem(inst, shape)
            return pre + asserts, []
        else:
            return pre, []
    elif isinstance(inst, ir.Branch):
        cond_var = inst.cond
        cond_def = guard(get_definition, self.func_ir, cond_var)
        if not cond_def:  # phi variable has no single definition
            # We'll use equiv_set to try to find a cond_def instead
            equivs = equiv_set.get_equiv_set(cond_var)
            defs = []
            for name in equivs:
                if isinstance(name, str) and name in self.typemap:
                    var_def = guard(get_definition, self.func_ir, name, lhs_only=True)
                    if isinstance(var_def, ir.Var):
                        var_def = var_def.name
                    if var_def:
                        defs.append(var_def)
                else:
                    defs.append(name)
            defvars = set(filter(lambda x: isinstance(x, str), defs))
            defconsts = set(defs).difference(defvars)
            if len(defconsts) == 1:
                cond_def = list(defconsts)[0]
            elif len(defvars) == 1:
                cond_def = guard(get_definition, self.func_ir, list(defvars)[0])
        if isinstance(cond_def, ir.Expr) and cond_def.op == "binop":
            br = None
            if cond_def.fn == operator.eq:
                br = inst.truebr
                otherbr = inst.falsebr
                cond_val = 1
            elif cond_def.fn == operator.ne:
                br = inst.falsebr
                otherbr = inst.truebr
                cond_val = 0
            lhs_typ = self.typemap[cond_def.lhs.name]
            rhs_typ = self.typemap[cond_def.rhs.name]
            if br != None and (
                (
                    isinstance(lhs_typ, types.Integer)
                    and isinstance(rhs_typ, types.Integer)
                )
                or (
                    isinstance(lhs_typ, types.BaseTuple)
                    and isinstance(rhs_typ, types.BaseTuple)
                )
            ):
                loc = inst.loc
                args = (cond_def.lhs, cond_def.rhs)
                asserts = self._make_assert_equiv(scope, loc, equiv_set, args)
                asserts.append(ir.Assign(ir.Const(cond_val, loc), cond_var, loc))
                self.prepends[(label, br)] = asserts
                self.prepends[(label, otherbr)] = [
                    ir.Assign(ir.Const(1 - cond_val, loc), cond_var, loc)
                ]
        else:
            if isinstance(cond_def, ir.Const):
                cond_def = cond_def.value
            if isinstance(cond_def, int) or isinstance(cond_def, bool):
                # condition is always true/false, prune the outgoing edge
                pruned_br = inst.falsebr if cond_def else inst.truebr
                if pruned_br in self.pruned_predecessors:
                    self.pruned_predecessors[pruned_br].append(label)
                else:
                    self.pruned_predecessors[pruned_br] = [label]

    elif type(inst) in array_analysis_extensions:
        # let external calls handle stmt if type matches
        f = array_analysis_extensions[type(inst)]
        pre, post = f(inst, equiv_set, self.typemap, self)

    return pre, post


# 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 _analyze_inst(self, label, scope, equiv_set, inst, redefined):
    pre = []
    post = []
    if config.DEBUG_ARRAY_OPT >= 2:
        print("analyze_inst:", inst)
    if isinstance(inst, ir.Assign):
        lhs = inst.target
        typ = self.typemap[lhs.name]
        shape = None
        if isinstance(typ, types.ArrayCompatible) and typ.ndim == 0:
            shape = ()
        elif isinstance(inst.value, ir.Expr):
            result = self._analyze_expr(scope, equiv_set, inst.value)
            if result:
                shape = result[0]
                pre = result[1]
                if len(result) > 2:
                    rhs = result[2]
                    inst.value = rhs
        elif isinstance(inst.value, ir.Var) or isinstance(inst.value, ir.Const):
            shape = inst.value

        if isinstance(shape, ir.Const):
            if isinstance(shape.value, tuple):
                loc = shape.loc
                shape = tuple(ir.Const(x, loc) for x in shape.value)
            elif isinstance(shape.value, int):
                shape = (shape,)
            else:
                shape = None
        elif isinstance(shape, ir.Var) and isinstance(
            self.typemap[shape.name], types.Integer
        ):
            shape = (shape,)
        elif isinstance(shape, WrapIndexMeta):
            """ Here we've got the special WrapIndexMeta object
                    back from analyzing a wrap_index call.  We define
                    the lhs and then get it's equivalence class then
                    add the mapping from the tuple of slice size and
                    dimensional size equivalence ids to the lhs
                    equivalence id.
                """
            equiv_set.define(lhs, redefined, self.func_ir, typ)
            lhs_ind = equiv_set._get_ind(lhs.name)
            if lhs_ind != -1:
                equiv_set.wrap_map[(shape.slice_size, shape.dim_size)] = lhs_ind
            return pre, post

        if isinstance(typ, types.ArrayCompatible):
            if (
                shape == None
                or isinstance(shape, tuple)
                or (isinstance(shape, ir.Var) and not equiv_set.has_shape(shape))
            ):
                (shape, post) = self._gen_shape_call(equiv_set, lhs, typ.ndim, shape)
        elif isinstance(typ, types.UniTuple):
            if shape and isinstance(typ.dtype, types.Integer):
                (shape, post) = self._gen_shape_call(equiv_set, lhs, len(typ), shape)

        if shape != None:
            equiv_set.insert_equiv(lhs, shape)
        equiv_set.define(lhs, redefined, self.func_ir, typ)
    elif isinstance(inst, ir.StaticSetItem) or isinstance(inst, ir.SetItem):
        index = inst.index if isinstance(inst, ir.SetItem) else inst.index_var
        result = guard(self._index_to_shape, scope, equiv_set, inst.target, index)
        if not result:
            return [], []
        if result[0] is not None:
            assert isinstance(inst, ir.SetItem)
            inst.index = result[0]
            # inst.index_var = result[0]
        result = result[1]
        (target_shape, pre) = result
        value_shape = equiv_set.get_shape(inst.value)
        if value_shape == ():  # constant
            equiv_set.set_shape_setitem(inst, target_shape)
            return pre, []
        elif value_shape != None:
            target_typ = self.typemap[inst.target.name]
            require(isinstance(target_typ, types.ArrayCompatible))
            target_ndim = target_typ.ndim
            shapes = [target_shape, value_shape]
            names = [inst.target.name, inst.value.name]
            shape, asserts = self._broadcast_assert_shapes(
                scope, equiv_set, inst.loc, shapes, names
            )
            n = len(shape)
            # shape dimension must be within target dimension
            assert target_ndim >= n
            equiv_set.set_shape_setitem(inst, shape)
            return pre + asserts, []
        else:
            return pre, []
    elif isinstance(inst, ir.Branch):
        cond_var = inst.cond
        cond_def = guard(get_definition, self.func_ir, cond_var)
        if not cond_def:  # phi variable has no single definition
            # We'll use equiv_set to try to find a cond_def instead
            equivs = equiv_set.get_equiv_set(cond_var)
            defs = []
            for name in equivs:
                if isinstance(name, str) and name in self.typemap:
                    var_def = guard(get_definition, self.func_ir, name, lhs_only=True)
                    if isinstance(var_def, ir.Var):
                        var_def = var_def.name
                    if var_def:
                        defs.append(var_def)
                else:
                    defs.append(name)
            defvars = set(filter(lambda x: isinstance(x, str), defs))
            defconsts = set(defs).difference(defvars)
            if len(defconsts) == 1:
                cond_def = list(defconsts)[0]
            elif len(defvars) == 1:
                cond_def = guard(get_definition, self.func_ir, list(defvars)[0])
        if isinstance(cond_def, ir.Expr) and cond_def.op == "binop":
            br = None
            if cond_def.fn == operator.eq:
                br = inst.truebr
                otherbr = inst.falsebr
                cond_val = 1
            elif cond_def.fn == operator.ne:
                br = inst.falsebr
                otherbr = inst.truebr
                cond_val = 0
            lhs_typ = self.typemap[cond_def.lhs.name]
            rhs_typ = self.typemap[cond_def.rhs.name]
            if br != None and (
                (
                    isinstance(lhs_typ, types.Integer)
                    and isinstance(rhs_typ, types.Integer)
                )
                or (
                    isinstance(lhs_typ, types.BaseTuple)
                    and isinstance(rhs_typ, types.BaseTuple)
                )
            ):
                loc = inst.loc
                args = (cond_def.lhs, cond_def.rhs)
                asserts = self._make_assert_equiv(scope, loc, equiv_set, args)
                asserts.append(ir.Assign(ir.Const(cond_val, loc), cond_var, loc))
                self.prepends[(label, br)] = asserts
                self.prepends[(label, otherbr)] = [
                    ir.Assign(ir.Const(1 - cond_val, loc), cond_var, loc)
                ]
        else:
            if isinstance(cond_def, ir.Const):
                cond_def = cond_def.value
            if isinstance(cond_def, int) or isinstance(cond_def, bool):
                # condition is always true/false, prune the outgoing edge
                pruned_br = inst.falsebr if cond_def else inst.truebr
                if pruned_br in self.pruned_predecessors:
                    self.pruned_predecessors[pruned_br].append(label)
                else:
                    self.pruned_predecessors[pruned_br] = [label]

    elif type(inst) in array_analysis_extensions:
        # let external calls handle stmt if type matches
        f = array_analysis_extensions[type(inst)]
        pre, post = f(inst, equiv_set, self.typemap, self)

    return pre, post