# Buggy code
def _get_names(self, obj):
    """Return a set of names for the given obj, where array and tuples
    are broken down to their individual shapes or elements. This is
    safe because both Numba array shapes and Python tuples are immutable.
    """
    if isinstance(obj, ir.Var) or isinstance(obj, str):
        name = obj if isinstance(obj, str) else obj.name
        typ = self.typemap[name]
        if isinstance(typ, types.BaseTuple) or isinstance(typ, types.ArrayCompatible):
            ndim = typ.ndim if isinstance(typ, types.ArrayCompatible) else len(typ)
            if ndim == 0:
                return ()
            else:
                return tuple("{}#{}".format(name, i) for i in range(ndim))
        else:
            return (name,)
    elif isinstance(obj, ir.Const):
        if isinstance(obj.value, tuple):
            return obj.value
        else:
            return (obj.value,)
    elif isinstance(obj, tuple):
        return tuple(self._get_names(x)[0] for x in obj)
    elif isinstance(obj, int):
        return (obj,)
    else:
        raise NotImplementedError("ShapeEquivSet does not support {}".format(obj))


# Traceback (IndexError)
Traceback (most recent call last):

File "<ipython-input-101-c2c55c205bd8>", line 1, in <module>
runfile('C:/Users/rpham/Desktop/FIN_Library/test.py', wdir='C:/Users/rpham/Desktop/FIN_Library')

File "C:\Users\rpham\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 827, in runfile
execfile(filename, namespace)

File "C:\Users\rpham\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/rpham/Desktop/FIN_Library/test.py", line 19, in <module>
result = fama_macbeth_numba(df,'period','ret',['exmkt','smb','hml'],intercept=True,parallel=True)

File "C:\Users\rpham\Desktop\FIN_Library\finance_byu\fama_macbeth.py", line 202, in fama_macbeth_numba
gammas = _ols_numba_parallel(d,ti,np.array(yvari),np.array(xvari))

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\dispatcher.py", line 370, in _compile_for_args
raise e

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\dispatcher.py", line 327, in _compile_for_args
return self.compile(tuple(argtypes))

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler_lock.py", line 32, in _acquire_compile_lock
return func(*args, **kwargs)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\dispatcher.py", line 659, in compile
cres = self._compiler.compile(args, return_type)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\dispatcher.py", line 83, in compile
pipeline_class=self.pipeline_class)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler.py", line 955, in compile_extra
return pipeline.compile_extra(func)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler.py", line 377, in compile_extra
return self._compile_bytecode()

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler.py", line 886, in _compile_bytecode
return self._compile_core()

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler.py", line 873, in _compile_core
res = pm.run(self.status)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler_lock.py", line 32, in _acquire_compile_lock
return func(*args, **kwargs)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler.py", line 254, in run
raise patched_exception

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler.py", line 245, in run
stage()

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\compiler.py", line 565, in stage_parfor_pass
parfor_pass.run()

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\parfor.py", line 1448, in run
self.array_analysis.run(self.func_ir.blocks)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\array_analysis.py", line 916, in run
pre, post = self._analyze_inst(label, scope, equiv_set, inst)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\array_analysis.py", line 987, in _analyze_inst
equiv_set.insert_equiv(lhs, shape)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\array_analysis.py", line 445, in insert_equiv
obj_names = [self._get_names(x) for x in objs]

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\array_analysis.py", line 445, in <listcomp>
obj_names = [self._get_names(x) for x in objs]

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\array_analysis.py", line 363, in _get_names
return tuple(self._get_names(x)[0] for x in obj)

File "C:\Users\rpham\Anaconda3\lib\site-packages\numba\array_analysis.py", line 363, in <genexpr>
return tuple(self._get_names(x)[0] for x in obj)

IndexError: Failed in nopython mode pipeline (step: convert to parfors)
tuple index out of range

# Fixed code
def _get_names(self, obj):
    """Return a set of names for the given obj, where array and tuples
    are broken down to their individual shapes or elements. This is
    safe because both Numba array shapes and Python tuples are immutable.
    """
    if isinstance(obj, ir.Var) or isinstance(obj, str):
        name = obj if isinstance(obj, str) else obj.name
        typ = self.typemap[name]
        if isinstance(typ, types.BaseTuple) or isinstance(typ, types.ArrayCompatible):
            ndim = typ.ndim if isinstance(typ, types.ArrayCompatible) else len(typ)
            # Treat 0d array as if it were a scalar.
            if ndim == 0:
                return (name,)
            else:
                return tuple("{}#{}".format(name, i) for i in range(ndim))
        else:
            return (name,)
    elif isinstance(obj, ir.Const):
        if isinstance(obj.value, tuple):
            return obj.value
        else:
            return (obj.value,)
    elif isinstance(obj, tuple):
        return tuple(self._get_names(x)[0] for x in obj)
    elif isinstance(obj, int):
        return (obj,)
    else:
        raise NotImplementedError("ShapeEquivSet does not support {}".format(obj))