# Buggy code
def _do_work(self, state, work_list, block, i, expr):
    from numba.core.inline_closurecall import inline_closure_call, callee_ir_validator
    from numba.core.compiler import run_frontend
    from numba.core.cpu import InlineOptions

    # try and get a definition for the call, this isn't always possible as
    # it might be a eval(str)/part generated awaiting update etc. (parfors)
    to_inline = None
    try:
        to_inline = state.func_ir.get_definition(expr.func)
    except Exception:
        if self._DEBUG:
            print("Cannot find definition for %s" % expr.func)
        return False
    # do not handle closure inlining here, another pass deals with that.
    if getattr(to_inline, "op", False) == "make_function":
        return False

    # see if the definition is a "getattr", in which case walk the IR to
    # try and find the python function via the module from which it's
    # imported, this should all be encoded in the IR.
    if getattr(to_inline, "op", False) == "getattr":
        val = resolve_func_from_module(state.func_ir, to_inline)
    else:
        # This is likely a freevar or global
        #
        # NOTE: getattr 'value' on a call may fail if it's an ir.Expr as
        # getattr is overloaded to look in _kws.
        try:
            val = getattr(to_inline, "value", False)
        except Exception:
            raise GuardException

    # if something was found...
    if val:
        # check it's dispatcher-like, the targetoptions attr holds the
        # kwargs supplied in the jit decorator and is where 'inline' will
        # be if it is present.
        topt = getattr(val, "targetoptions", False)
        if topt:
            inline_type = topt.get("inline", None)
            # has 'inline' been specified?
            if inline_type is not None:
                inline_opt = InlineOptions(inline_type)
                # Could this be inlinable?
                if not inline_opt.is_never_inline:
                    # yes, it could be inlinable
                    do_inline = True
                    pyfunc = val.py_func
                    # Has it got an associated cost model?
                    if inline_opt.has_cost_model:
                        # yes, it has a cost model, use it to determine
                        # whether to do the inline
                        py_func_ir = run_frontend(pyfunc)
                        do_inline = inline_type(expr, state.func_ir, py_func_ir)
                    # if do_inline is True then inline!
                    if do_inline:
                        inline_closure_call(
                            state.func_ir,
                            pyfunc.__globals__,
                            block,
                            i,
                            pyfunc,
                            work_list=work_list,
                            callee_validator=callee_ir_validator,
                        )
                        return True
    return False


# Traceback (ValueError)
Traceback (most recent call last):
File "test_inline.py", line 14, in <module>
print(fn())
File "numba\numba\dispatcher.py", line 420, in _compile_for_args
raise e
File "numba\numba\dispatcher.py", line 353, in _compile_for_args
return self.compile(tuple(argtypes))
File "numba\numba\compiler_lock.py", line 32, in _acquire_compile_lock
return func(*args, **kwargs)
File "numba\numba\dispatcher.py", line 768, in compile
cres = self._compiler.compile(args, return_type)
File "numba\numba\dispatcher.py", line 77, in compile
status, retval = self._compile_cached(args, return_type)
File "numba\numba\dispatcher.py", line 91, in _compile_cached
retval = self._compile_core(args, return_type)
File "numba\numba\dispatcher.py", line 109, in _compile_core
pipeline_class=self.pipeline_class)
File "numba\numba\compiler.py", line 551, in compile_extra
return pipeline.compile_extra(func)
File "numba\numba\compiler.py", line 331, in compile_extra
return self._compile_bytecode()
File "numba\numba\compiler.py", line 393, in _compile_bytecode
return self._compile_core()
File "numba\numba\compiler.py", line 373, in _compile_core
raise e
File "numba\numba\compiler.py", line 364, in _compile_core
pm.run(self.state)
File "numba\numba\compiler_machinery.py", line 347, in run
raise patched_exception
File "numba\numba\compiler_machinery.py", line 338, in run
self._runPass(idx, pass_inst, state)
File "numba\numba\compiler_lock.py", line 32, in _acquire_compile_lock
return func(*args, **kwargs)
File "numba\numba\compiler_machinery.py", line 302, in _runPass
mutated |= check(pss.run_pass, internal_state)
File "numba\numba\compiler_machinery.py", line 275, in check
mangled = func(compiler_state)
File "numba\numba\untyped_passes.py", line 312, in run_pass
state.func_ir.blocks = simplify_CFG(state.func_ir.blocks)
File "numba\numba\ir_utils.py", line 1237, in simplify_CFG
return rename_labels(blocks)
File "numba\numba\ir_utils.py", line 1188, in rename_labels
topo_order.remove(return_label)
ValueError: Failed in nopython mode pipeline (step: inline inlinable functions)
list.remove(x): x not in list

# Fixed code
def _do_work(self, state, work_list, block, i, expr, inline_worker):
    from numba.core.compiler import run_frontend
    from numba.core.cpu import InlineOptions

    # try and get a definition for the call, this isn't always possible as
    # it might be a eval(str)/part generated awaiting update etc. (parfors)
    to_inline = None
    try:
        to_inline = state.func_ir.get_definition(expr.func)
    except Exception:
        if self._DEBUG:
            print("Cannot find definition for %s" % expr.func)
        return False
    # do not handle closure inlining here, another pass deals with that.
    if getattr(to_inline, "op", False) == "make_function":
        return False

    # see if the definition is a "getattr", in which case walk the IR to
    # try and find the python function via the module from which it's
    # imported, this should all be encoded in the IR.
    if getattr(to_inline, "op", False) == "getattr":
        val = resolve_func_from_module(state.func_ir, to_inline)
    else:
        # This is likely a freevar or global
        #
        # NOTE: getattr 'value' on a call may fail if it's an ir.Expr as
        # getattr is overloaded to look in _kws.
        try:
            val = getattr(to_inline, "value", False)
        except Exception:
            raise GuardException

    # if something was found...
    if val:
        # check it's dispatcher-like, the targetoptions attr holds the
        # kwargs supplied in the jit decorator and is where 'inline' will
        # be if it is present.
        topt = getattr(val, "targetoptions", False)
        if topt:
            inline_type = topt.get("inline", None)
            # has 'inline' been specified?
            if inline_type is not None:
                inline_opt = InlineOptions(inline_type)
                # Could this be inlinable?
                if not inline_opt.is_never_inline:
                    # yes, it could be inlinable
                    do_inline = True
                    pyfunc = val.py_func
                    # Has it got an associated cost model?
                    if inline_opt.has_cost_model:
                        # yes, it has a cost model, use it to determine
                        # whether to do the inline
                        py_func_ir = run_frontend(pyfunc)
                        do_inline = inline_type(expr, state.func_ir, py_func_ir)
                    # if do_inline is True then inline!
                    if do_inline:
                        _, _, _, new_blocks = inline_worker.inline_function(
                            state.func_ir,
                            block,
                            i,
                            pyfunc,
                        )
                        if work_list is not None:
                            for blk in new_blocks:
                                work_list.append(blk)
                        return True
    return False