# Buggy code
def generic(self, args, kws):
    """
    Type the overloaded function by compiling the appropriate
    implementation for the given args.
    """
    disp, new_args = self._get_impl(args, kws)
    if disp is None:
        return
    # Compile and type it for the given types
    disp_type = types.Dispatcher(disp)
    # Store the compiled overload for use in the lowering phase if there's
    # no inlining required (else functions are being compiled which will
    # never be used as they are inlined)
    if not self._inline.is_never_inline:
        # need to run the compiler front end up to type inference to compute
        # a signature
        from numba.core import typed_passes, compiler
        from numba.core.inline_closurecall import InlineWorker

        fcomp = disp._compiler
        flags = compiler.Flags()

        # Updating these causes problems?!
        # fcomp.targetdescr.options.parse_as_flags(flags,
        #                                         fcomp.targetoptions)
        # flags = fcomp._customize_flags(flags)

        # spoof a compiler pipline like the one that will be in use
        tyctx = fcomp.targetdescr.typing_context
        tgctx = fcomp.targetdescr.target_context
        compiler_inst = fcomp.pipeline_class(
            tyctx,
            tgctx,
            None,
            None,
            None,
            flags,
            None,
        )
        inline_worker = InlineWorker(
            tyctx,
            tgctx,
            fcomp.locals,
            compiler_inst,
            flags,
            None,
        )

        ir = inline_worker.run_untyped_passes(disp_type.dispatcher.py_func)
        resolve = disp_type.dispatcher.get_call_template
        template, pysig, folded_args, kws = resolve(new_args, kws)

        typemap, return_type, calltypes = typed_passes.type_inference_stage(
            self.context, ir, folded_args, None
        )
        sig = Signature(return_type, folded_args, None)
        # this stores a load of info for the cost model function if supplied
        # it by default is None
        self._inline_overloads[sig.args] = {"folded_args": folded_args}
        # this stores the compiled overloads, if there's no compiled
        # overload available i.e. function is always inlined, the key still
        # needs to exist for type resolution

        # NOTE: If lowering is failing on a `_EmptyImplementationEntry`,
        #       the inliner has failed to inline this entry corretly.
        impl_init = _EmptyImplementationEntry("always inlined")
        self._compiled_overloads[sig.args] = impl_init
        if not self._inline.is_always_inline:
            # this branch is here because a user has supplied a function to
            # determine whether to inline or not. As a result both compiled
            # function and inliner info needed, delaying the computation of
            # this leads to an internal state mess at present. TODO: Fix!
            sig = disp_type.get_call_type(self.context, new_args, kws)
            self._compiled_overloads[sig.args] = disp_type.get_overload(sig)
            # store the inliner information, it's used later in the cost
            # model function call
        iinfo = _inline_info(ir, typemap, calltypes, sig)
        self._inline_overloads[sig.args] = {"folded_args": folded_args, "iinfo": iinfo}
    else:
        sig = disp_type.get_call_type(self.context, new_args, kws)
        self._compiled_overloads[sig.args] = disp_type.get_overload(sig)
    return sig


# Traceback (numba.core.errors.TypingError)
DEBUG: dtype= unicode_type
Traceback (most recent call last):
File "test_inline_literally.py", line 36, in <module>
res = test_impl(data, dtype)
File "C:\Users\akozlov\AppData\Local\Continuum\anaconda3\numba_master\numba\numba\core\dispatcher.py", line 401, in _compile_for_args
error_rewrite(e, 'typing')
File "C:\Users\akozlov\AppData\Local\Continuum\anaconda3\numba_master\numba\numba\core\dispatcher.py", line 344, in error_rewrite
reraise(type(e), e, None)
File "C:\Users\akozlov\AppData\Local\Continuum\anaconda3\numba_master\numba\numba\core\utils.py", line 79, in reraise
raise value.with_traceback(tb)
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Internal error at <numba.core.typeinfer.CallConstraint object at 0x0000023CF5AA24F0>.
'NoneType' object is not callable
[1] During: resolving callee type: Function(<function foo at 0x0000023CF24E5280>)
[2] During: typing of call at test_inline_literally.py (32)

Enable logging at debug level for details.

File "test_inline_literally.py", line 32:
def test_impl(arr, dtype):
return foo(arr, dtype)
^

# Fixed code
def generic(self, args, kws):
    """
    Type the overloaded function by compiling the appropriate
    implementation for the given args.
    """
    disp, new_args = self._get_impl(args, kws)
    if disp is None:
        return
    # Compile and type it for the given types
    disp_type = types.Dispatcher(disp)
    # Store the compiled overload for use in the lowering phase if there's
    # no inlining required (else functions are being compiled which will
    # never be used as they are inlined)
    if not self._inline.is_never_inline:
        # need to run the compiler front end up to type inference to compute
        # a signature
        from numba.core import typed_passes, compiler
        from numba.core.inline_closurecall import InlineWorker

        fcomp = disp._compiler
        flags = compiler.Flags()

        # Updating these causes problems?!
        # fcomp.targetdescr.options.parse_as_flags(flags,
        #                                         fcomp.targetoptions)
        # flags = fcomp._customize_flags(flags)

        # spoof a compiler pipline like the one that will be in use
        tyctx = fcomp.targetdescr.typing_context
        tgctx = fcomp.targetdescr.target_context
        compiler_inst = fcomp.pipeline_class(
            tyctx,
            tgctx,
            None,
            None,
            None,
            flags,
            None,
        )
        inline_worker = InlineWorker(
            tyctx,
            tgctx,
            fcomp.locals,
            compiler_inst,
            flags,
            None,
        )

        # If the inlinee contains something to trigger literal arg dispatch
        # then the pipeline call will unconditionally fail due to a raised
        # ForceLiteralArg exception. Therefore `resolve` is run first, as
        # type resolution must occur at some point, this will hit any
        # `literally` calls and because it's going via the dispatcher will
        # handle them correctly i.e. ForceLiteralArg propagates. This having
        # the desired effect of ensuring the pipeline call is only made in
        # situations that will succeed. For context see #5887.
        resolve = disp_type.dispatcher.get_call_template
        template, pysig, folded_args, kws = resolve(new_args, kws)
        ir = inline_worker.run_untyped_passes(disp_type.dispatcher.py_func)

        typemap, return_type, calltypes = typed_passes.type_inference_stage(
            self.context, ir, folded_args, None
        )
        sig = Signature(return_type, folded_args, None)
        # this stores a load of info for the cost model function if supplied
        # it by default is None
        self._inline_overloads[sig.args] = {"folded_args": folded_args}
        # this stores the compiled overloads, if there's no compiled
        # overload available i.e. function is always inlined, the key still
        # needs to exist for type resolution

        # NOTE: If lowering is failing on a `_EmptyImplementationEntry`,
        #       the inliner has failed to inline this entry corretly.
        impl_init = _EmptyImplementationEntry("always inlined")
        self._compiled_overloads[sig.args] = impl_init
        if not self._inline.is_always_inline:
            # this branch is here because a user has supplied a function to
            # determine whether to inline or not. As a result both compiled
            # function and inliner info needed, delaying the computation of
            # this leads to an internal state mess at present. TODO: Fix!
            sig = disp_type.get_call_type(self.context, new_args, kws)
            self._compiled_overloads[sig.args] = disp_type.get_overload(sig)
            # store the inliner information, it's used later in the cost
            # model function call
        iinfo = _inline_info(ir, typemap, calltypes, sig)
        self._inline_overloads[sig.args] = {"folded_args": folded_args, "iinfo": iinfo}
    else:
        sig = disp_type.get_call_type(self.context, new_args, kws)
        self._compiled_overloads[sig.args] = disp_type.get_overload(sig)
    return sig