# Buggy code
def run(self):
    """run parfor conversion pass: replace Numpy calls
    with Parfors when possible and optimize the IR."""
    # run array analysis, a pre-requisite for parfor translation
    remove_dels(self.func_ir.blocks)
    self.array_analysis.run(self.func_ir.blocks)
    # run stencil translation to parfor
    if self.options.stencil:
        stencil_pass = StencilPass(
            self.func_ir,
            self.typemap,
            self.calltypes,
            self.array_analysis,
            self.typingctx,
            self.flags,
        )
        stencil_pass.run()
    if self.options.setitem:
        self._convert_setitem(self.func_ir.blocks)
    if self.options.numpy:
        self._convert_numpy(self.func_ir.blocks)
    if self.options.reduction:
        self._convert_reduce(self.func_ir.blocks)
    if self.options.prange:
        self._convert_loop(self.func_ir.blocks)

    # setup diagnostics now parfors are found
    self.diagnostics.setup(self.func_ir, self.options.fusion)

    dprint_func_ir(self.func_ir, "after parfor pass")

    # simplify CFG of parfor body loops since nested parfors with extra
    # jumps can be created with prange conversion
    simplify_parfor_body_CFG(self.func_ir.blocks)
    # simplify before fusion
    simplify(self.func_ir, self.typemap, self.calltypes)
    # need two rounds of copy propagation to enable fusion of long sequences
    # of parfors like test_fuse_argmin (some PYTHONHASHSEED values since
    # apply_copies_parfor depends on set order for creating dummy assigns)
    simplify(self.func_ir, self.typemap, self.calltypes)

    if self.options.fusion:
        self.func_ir._definitions = build_definitions(self.func_ir.blocks)
        self.array_analysis.equiv_sets = dict()
        self.array_analysis.run(self.func_ir.blocks)
        # reorder statements to maximize fusion
        # push non-parfors down
        maximize_fusion(
            self.func_ir, self.func_ir.blocks, self.typemap, up_direction=False
        )
        dprint_func_ir(self.func_ir, "after maximize fusion down")
        self.fuse_parfors(self.array_analysis, self.func_ir.blocks)
        # push non-parfors up
        maximize_fusion(self.func_ir, self.func_ir.blocks, self.typemap)
        dprint_func_ir(self.func_ir, "after maximize fusion up")
        # try fuse again after maximize
        self.fuse_parfors(self.array_analysis, self.func_ir.blocks)
        dprint_func_ir(self.func_ir, "after fusion")
    # simplify again
    simplify(self.func_ir, self.typemap, self.calltypes)
    # push function call variables inside parfors so gufunc function
    # wouldn't need function variables as argument
    push_call_vars(self.func_ir.blocks, {}, {})
    # simplify again
    simplify(self.func_ir, self.typemap, self.calltypes)
    dprint_func_ir(self.func_ir, "after optimization")
    if config.DEBUG_ARRAY_OPT >= 1:
        print("variable types: ", sorted(self.typemap.items()))
        print("call types: ", self.calltypes)
    # run post processor again to generate Del nodes
    post_proc = postproc.PostProcessor(self.func_ir)
    post_proc.run()
    if self.func_ir.is_generator:
        fix_generator_types(self.func_ir.generator_info, self.return_type, self.typemap)
    if sequential_parfor_lowering:
        lower_parfor_sequential(
            self.typingctx, self.func_ir, self.typemap, self.calltypes
        )
    else:
        # prepare for parallel lowering
        # add parfor params to parfors here since lowering is destructive
        # changing the IR after this is not allowed
        parfor_ids, parfors = get_parfor_params(
            self.func_ir.blocks, self.options.fusion, self.nested_fusion_info
        )
        for p in parfors:
            numba.parfor.get_parfor_reductions(
                self.func_ir, p, p.params, self.calltypes
            )
        if config.DEBUG_ARRAY_OPT_STATS:
            name = self.func_ir.func_id.func_qualname
            n_parfors = len(parfor_ids)
            if n_parfors > 0:
                after_fusion = (
                    "After fusion" if self.options.fusion else "With fusion disabled"
                )
                print(
                    ("{}, function {} has {} parallel for-loop(s) #{}.").format(
                        after_fusion, name, n_parfors, parfor_ids
                    )
                )
            else:
                print("Function {} has no Parfor.".format(name))

    return


# 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 run(self):
    """run parfor conversion pass: replace Numpy calls
    with Parfors when possible and optimize the IR."""
    # run array analysis, a pre-requisite for parfor translation
    remove_dels(self.func_ir.blocks)
    self.array_analysis.run(self.func_ir.blocks)
    # run stencil translation to parfor
    if self.options.stencil:
        stencil_pass = StencilPass(
            self.func_ir,
            self.typemap,
            self.calltypes,
            self.array_analysis,
            self.typingctx,
            self.flags,
        )
        stencil_pass.run()
    if self.options.setitem:
        self._convert_setitem(self.func_ir.blocks)
    if self.options.numpy:
        self._convert_numpy(self.func_ir.blocks)
    if self.options.reduction:
        self._convert_reduce(self.func_ir.blocks)
    if self.options.prange:
        self._convert_loop(self.func_ir.blocks)

    # setup diagnostics now parfors are found
    self.diagnostics.setup(self.func_ir, self.options.fusion)

    dprint_func_ir(self.func_ir, "after parfor pass")

    # simplify CFG of parfor body loops since nested parfors with extra
    # jumps can be created with prange conversion
    simplify_parfor_body_CFG(self.func_ir.blocks)
    # simplify before fusion
    simplify(self.func_ir, self.typemap, self.calltypes)
    # need two rounds of copy propagation to enable fusion of long sequences
    # of parfors like test_fuse_argmin (some PYTHONHASHSEED values since
    # apply_copies_parfor depends on set order for creating dummy assigns)
    simplify(self.func_ir, self.typemap, self.calltypes)

    if self.options.fusion:
        self.func_ir._definitions = build_definitions(self.func_ir.blocks)
        self.array_analysis.equiv_sets = dict()
        self.array_analysis.run(self.func_ir.blocks)
        # reorder statements to maximize fusion
        # push non-parfors down
        maximize_fusion(
            self.func_ir, self.func_ir.blocks, self.typemap, up_direction=False
        )
        dprint_func_ir(self.func_ir, "after maximize fusion down")
        self.fuse_parfors(self.array_analysis, self.func_ir.blocks)
        # push non-parfors up
        maximize_fusion(self.func_ir, self.func_ir.blocks, self.typemap)
        dprint_func_ir(self.func_ir, "after maximize fusion up")
        # try fuse again after maximize
        self.fuse_parfors(self.array_analysis, self.func_ir.blocks)
        dprint_func_ir(self.func_ir, "after fusion")
    # simplify again
    simplify(self.func_ir, self.typemap, self.calltypes)
    # push function call variables inside parfors so gufunc function
    # wouldn't need function variables as argument
    push_call_vars(self.func_ir.blocks, {}, {})
    # simplify again
    simplify(self.func_ir, self.typemap, self.calltypes)
    dprint_func_ir(self.func_ir, "after optimization")
    if config.DEBUG_ARRAY_OPT >= 1:
        print("variable types: ", sorted(self.typemap.items()))
        print("call types: ", self.calltypes)

    if config.DEBUG_ARRAY_OPT >= 3:
        for block_label, block in self.func_ir.blocks.items():
            new_block = []
            scope = block.scope
            for stmt in block.body:
                new_block.append(stmt)
                if isinstance(stmt, ir.Assign):
                    loc = stmt.loc
                    lhs = stmt.target
                    rhs = stmt.value
                    lhs_typ = self.typemap[lhs.name]
                    print(
                        "Adding print for assignment to ",
                        lhs.name,
                        lhs_typ,
                        type(lhs_typ),
                    )
                    if lhs_typ in types.number_domain or isinstance(
                        lhs_typ, types.Literal
                    ):
                        str_var = ir.Var(scope, mk_unique_var("str_var"), loc)
                        self.typemap[str_var.name] = types.StringLiteral(lhs.name)
                        lhs_const = ir.Const(lhs.name, loc)
                        str_assign = ir.Assign(lhs_const, str_var, loc)
                        new_block.append(str_assign)
                        str_print = ir.Print([str_var], None, loc)
                        self.calltypes[str_print] = signature(
                            types.none, self.typemap[str_var.name]
                        )
                        new_block.append(str_print)
                        ir_print = ir.Print([lhs], None, loc)
                        self.calltypes[ir_print] = signature(types.none, lhs_typ)
                        new_block.append(ir_print)
            block.body = new_block

    # run post processor again to generate Del nodes
    post_proc = postproc.PostProcessor(self.func_ir)
    post_proc.run()
    if self.func_ir.is_generator:
        fix_generator_types(self.func_ir.generator_info, self.return_type, self.typemap)
    if sequential_parfor_lowering:
        lower_parfor_sequential(
            self.typingctx, self.func_ir, self.typemap, self.calltypes
        )
    else:
        # prepare for parallel lowering
        # add parfor params to parfors here since lowering is destructive
        # changing the IR after this is not allowed
        parfor_ids, parfors = get_parfor_params(
            self.func_ir.blocks, self.options.fusion, self.nested_fusion_info
        )
        for p in parfors:
            numba.parfor.get_parfor_reductions(
                self.func_ir, p, p.params, self.calltypes
            )
        if config.DEBUG_ARRAY_OPT_STATS:
            name = self.func_ir.func_id.func_qualname
            n_parfors = len(parfor_ids)
            if n_parfors > 0:
                after_fusion = (
                    "After fusion" if self.options.fusion else "With fusion disabled"
                )
                print(
                    ("{}, function {} has {} parallel for-loop(s) #{}.").format(
                        after_fusion, name, n_parfors, parfor_ids
                    )
                )
            else:
                print("Function {} has no Parfor.".format(name))

    return