# Buggy code
def _compile_core(self, sig, flags, locals):
    """
    Trigger the compiler on the core function or load a previously
    compiled version from the cache.  Returns the CompileResult.
    """
    typingctx = self.targetdescr.typing_context
    targetctx = self.targetdescr.target_context

    @contextmanager
    def store_overloads_on_success():
        # use to ensure overloads are stored on success
        try:
            yield
        except:
            raise
        else:
            exists = self.overloads.get(cres.signature)
            if exists is None:
                self.overloads[cres.signature] = cres

    # Use cache and compiler in a critical section
    with global_compiler_lock:
        with store_overloads_on_success():
            # attempt look up of existing
            cres = self.cache.load_overload(sig, targetctx)
            if cres is not None:
                return cres

            # Compile
            args, return_type = sigutils.normalize_signature(sig)
            cres = compiler.compile_extra(
                typingctx,
                targetctx,
                self.py_func,
                args=args,
                return_type=return_type,
                flags=flags,
                locals=locals,
            )

            # cache lookup failed before so safe to save
            self.cache.save_overload(sig, cres)

            return cres


# Traceback (TypeError)
<class 'numpy.ufunc'>
b'\x80\x03cnumpy.core\n_ufunc_reconstruct\nq\x00X\x0b\x00\x00\x00__mp_main__q\x01X\x04\x00\x00\x00inc2q\x02\x86q\x03Rq\x04.'
<class 'numba.npyufunc.dufunc.DUFunc'>
Traceback (most recent call last):
File "vectorize_pickle.py", line 15, in <module>
print(pickle.dumps(inc1))
TypeError: can't pickle DUFunc objects

# Fixed code
def _compile_core(self, sig, flags, locals):
    """
    Trigger the compiler on the core function or load a previously
    compiled version from the cache.  Returns the CompileResult.
    """
    typingctx = self.targetdescr.typing_context
    targetctx = self.targetdescr.target_context

    @contextmanager
    def store_overloads_on_success():
        # use to ensure overloads are stored on success
        try:
            yield
        except Exception:
            raise
        else:
            exists = self.overloads.get(cres.signature)
            if exists is None:
                self.overloads[cres.signature] = cres

    # Use cache and compiler in a critical section
    with global_compiler_lock:
        with store_overloads_on_success():
            # attempt look up of existing
            cres = self.cache.load_overload(sig, targetctx)
            if cres is not None:
                return cres

            # Compile
            args, return_type = sigutils.normalize_signature(sig)
            cres = compiler.compile_extra(
                typingctx,
                targetctx,
                self.py_func,
                args=args,
                return_type=return_type,
                flags=flags,
                locals=locals,
            )

            # cache lookup failed before so safe to save
            self.cache.save_overload(sig, cres)

            return cres