# Buggy code
def get_array_index_type(ary, idx):
    """
    Returns None or a tuple-3 for the types of the input array, index, and
    resulting type of ``array[index]``.

    Note: This is shared logic for ndarray getitem and setitem.
    """
    if not isinstance(ary, types.Buffer):
        return

    ndim = ary.ndim

    left_indices = []
    right_indices = []
    ellipsis_met = False
    advanced = False
    has_integer = False

    if not isinstance(idx, types.BaseTuple):
        idx = [idx]

    # Walk indices
    for ty in idx:
        if ty is types.ellipsis:
            if ellipsis_met:
                raise TypeError(
                    "only one ellipsis allowed in array index (got %s)" % (idx,)
                )
            ellipsis_met = True
        elif isinstance(ty, types.SliceType):
            pass
        elif isinstance(ty, types.Integer):
            # Normalize integer index
            ty = types.intp if ty.signed else types.uintp
            # Integer indexing removes the given dimension
            ndim -= 1
            has_integer = True
        elif (
            isinstance(ty, types.Array)
            and ty.ndim == 0
            and isinstance(ty.dtype, types.Integer)
        ):
            # 0-d array used as integer index
            ndim -= 1
            has_integer = True
        elif (
            isinstance(ty, types.Array)
            and ty.ndim == 1
            and isinstance(ty.dtype, (types.Integer, types.Boolean))
        ):
            if advanced or has_integer:
                # We don't support the complicated combination of
                # advanced indices (and integers are considered part
                # of them by Numpy).
                raise NotImplementedError("only one advanced index supported")
            advanced = True
        else:
            raise TypeError("unsupported array index type %s in %s" % (ty, idx))
        (right_indices if ellipsis_met else left_indices).append(ty)

    # Only Numpy arrays support advanced indexing
    if advanced and not isinstance(ary, types.Array):
        return

    # Check indices and result dimensionality
    all_indices = left_indices + right_indices
    if ellipsis_met:
        assert right_indices[0] is types.ellipsis
        del right_indices[0]

    n_indices = len(all_indices) - ellipsis_met
    if n_indices > ary.ndim:
        raise TypeError("cannot index %s with %d indices: %s" % (ary, n_indices, idx))
    if n_indices == ary.ndim and ndim == 0 and not ellipsis_met:
        # Full integer indexing => scalar result
        # (note if ellipsis is present, a 0-d view is returned instead)
        res = ary.dtype

    elif advanced:
        # Result is a copy
        res = ary.copy(ndim=ndim, layout="C", readonly=False)

    else:
        # Result is a view
        if ary.slice_is_copy:
            # Avoid view semantics when the original type creates a copy
            # when slicing.
            return

        # Infer layout
        layout = ary.layout

        def keeps_contiguity(ty, is_innermost):
            # A slice can only keep an array contiguous if it is the
            # innermost index and it is not strided
            return (
                ty is types.ellipsis
                or isinstance(ty, types.Integer)
                or (
                    is_innermost and isinstance(ty, types.SliceType) and not ty.has_step
                )
            )

        def check_contiguity(outer_indices):
            """
            Whether indexing with the given indices (from outer to inner in
            physical layout order) can keep an array contiguous.
            """
            for ty in outer_indices[:-1]:
                if not keeps_contiguity(ty, False):
                    return False
            if outer_indices and not keeps_contiguity(outer_indices[-1], True):
                return False
            return True

        if layout == "C":
            # Integer indexing on the left keeps the array C-contiguous
            if n_indices == ary.ndim:
                # If all indices are there, ellipsis's place is indifferent
                left_indices = left_indices + right_indices
                right_indices = []
            if right_indices:
                layout = "A"
            elif not check_contiguity(left_indices):
                layout = "A"
        elif layout == "F":
            # Integer indexing on the right keeps the array F-contiguous
            if n_indices == ary.ndim:
                # If all indices are there, ellipsis's place is indifferent
                right_indices = left_indices + right_indices
                left_indices = []
            if left_indices:
                layout = "A"
            elif not check_contiguity(right_indices[::-1]):
                layout = "A"

        res = ary.copy(ndim=ndim, layout=layout)

    # Re-wrap indices
    if isinstance(idx, types.BaseTuple):
        idx = types.BaseTuple.from_types(all_indices)
    else:
        (idx,) = all_indices

    return Indexing(idx, res, advanced)


# Traceback (NotImplementedError)
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/targets/base.py in cast(self, builder, val, fromty, toty)
674         try:
--> 675             impl = self._casts.find((fromty, toty))
676             return impl(self, builder, fromty, toty, val)

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/targets/base.py in find(self, sig)
47         if out is None:
---> 48             out = self._find(sig)
49             self._cache[sig] = out

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/targets/base.py in _find(self, sig)
56         else:
---> 57             raise NotImplementedError(self, sig)
58

NotImplementedError: (<numba.targets.base.OverloadSelector object at 0x1059269e8>, (array(float64, 0d, C), float64))

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call last)
~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/errors.py in new_error_context(fmt_, *args, **kwargs)
576     try:
--> 577         yield
578     except NumbaError as e:

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/lowering.py in lower_block(self, block)
253                                    loc=self.loc, errcls_=defaulterrcls):
--> 254                 self.lower_inst(inst)
255

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/lowering.py in lower_inst(self, inst)
357             assert signature is not None
--> 358             return self.lower_setitem(inst.target, inst.index, inst.value, signature)
359

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/lowering.py in lower_setitem(self, target_var, index_var, value_var, signature)
429
--> 430         return impl(self.builder, (target, index, value))
431

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/targets/base.py in __call__(self, builder, args)
1078     def __call__(self, builder, args):
-> 1079         return self._imp(self._context, builder, self._sig, args)
1080

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/targets/arrayobj.py in setitem_array(context, builder, sig, args)
481     # Store source value the given location
--> 482     val = context.cast(builder, val, valty, aryty.dtype)
483     store_item(context, builder, aryty, val, dataptr)

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/targets/base.py in cast(self, builder, val, fromty, toty)
678             raise NotImplementedError(
--> 679                 "Cannot cast %s to %s: %s" % (fromty, toty, val))
680

NotImplementedError: Cannot cast array(float64, 0d, C) to float64: %".417" = load {i8*, i8*, i64, i64, double*, [0 x i64], [0 x i64]}, {i8*, i8*, i64, i64, double*, [0 x i64], [0 x i64]}* %"$22.9"

During handling of the above exception, another exception occurred:

LoweringError                             Traceback (most recent call last)
<ipython-input-6-e6ce0775290a> in <module>()
----> 1 jitted(A[0], B[0], indices)

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/dispatcher.py in _compile_for_args(self, *args, **kws)
366                     e.patch_message(''.join(e.args) + help_msg)
367             # ignore the FULL_TRACEBACKS config, this needs reporting!
--> 368             raise e
369
370     def inspect_llvm(self, signature=None):

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/dispatcher.py in _compile_for_args(self, *args, **kws)
323                 argtypes.append(self.typeof_pyval(a))
324         try:
--> 325             return self.compile(tuple(argtypes))
326         except errors.TypingError as e:
327             # Intercept typing error that may be due to an argument

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/dispatcher.py in compile(self, sig)
651
652                 self._cache_misses[sig] += 1
--> 653                 cres = self._compiler.compile(args, return_type)
654                 self.add_overload(cres)
655                 self._cache.save_overload(sig, cres)

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/dispatcher.py in compile(self, args, return_type)
81                                       args=args, return_type=return_type,
82                                       flags=flags, locals=self.locals,
---> 83                                       pipeline_class=self.pipeline_class)
84         # Check typing error if object mode is used
85         if cres.typing_error is not None and not flags.enable_pyobject:

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library, pipeline_class)
871     pipeline = pipeline_class(typingctx, targetctx, library,
872                               args, return_type, flags, locals)
--> 873     return pipeline.compile_extra(func)
874
875

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in compile_extra(self, func)
365         self.lifted = ()
366         self.lifted_from = None
--> 367         return self._compile_bytecode()
368
369     def compile_ir(self, func_ir, lifted=(), lifted_from=None):

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in _compile_bytecode(self)
802         """
803         assert self.func_ir is None
--> 804         return self._compile_core()
805
806     def _compile_ir(self):

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in _compile_core(self)
789         self.define_pipelines(pm)
790         pm.finalize()
--> 791         res = pm.run(self.status)
792         if res is not None:
793             # Early pipeline completion

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in run(self, status)
251                     # No more fallback pipelines?
252                     if is_final_pipeline:
--> 253                         raise patched_exception
254                     # Go to next fallback pipeline
255                     else:

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in run(self, status)
243                 try:
244                     event(stage_name)
--> 245                     stage()
246                 except _EarlyPipelineCompletion as e:
247                     return e.result

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in stage_nopython_backend(self)
676         """
677         lowerfn = self.backend_nopython_mode
--> 678         self._backend(lowerfn, objectmode=False)
679
680     def stage_compile_interp_mode(self):

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in _backend(self, lowerfn, objectmode)
626             self.library.enable_object_caching()
627
--> 628         lowered = lowerfn()
629         signature = typing.signature(self.return_type, *self.args)
630         self.cr = compile_result(

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in backend_nopython_mode(self)
613                 self.return_type,
614                 self.calltypes,
--> 615                 self.flags)
616
617     def _backend(self, lowerfn, objectmode):

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/compiler.py in native_lowering_stage(targetctx, library, interp, typemap, restype, calltypes, flags)
990
991     lower = lowering.Lower(targetctx, library, fndesc, interp)
--> 992     lower.lower()
993     if not flags.no_cpython_wrapper:
994         lower.create_cpython_wrapper(flags.release_gil)

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/lowering.py in lower(self)
171         if self.generator_info is None:
172             self.genlower = None
--> 173             self.lower_normal_function(self.fndesc)
174         else:
175             self.genlower = self.GeneratorLower(self)

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/lowering.py in lower_normal_function(self, fndesc)
212         # Init argument values
213         self.extract_function_arguments()
--> 214         entry_block_tail = self.lower_function_body()
215
216         # Close tail of entry block

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/lowering.py in lower_function_body(self)
237             bb = self.blkmap[offset]
238             self.builder.position_at_end(bb)
--> 239             self.lower_block(block)
240
241         self.post_lower()

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/lowering.py in lower_block(self, block)
252             with new_error_context('lowering "{inst}" at {loc}', inst=inst,
253                                    loc=self.loc, errcls_=defaulterrcls):
--> 254                 self.lower_inst(inst)
255
256     def create_cpython_wrapper(self, release_gil=False):

~/miniconda3/envs/numba3/lib/python3.7/contextlib.py in __exit__(self, type, value, traceback)
128                 value = type()
129             try:
--> 130                 self.gen.throw(type, value, traceback)
131             except StopIteration as exc:
132                 # Suppress StopIteration *unless* it's the same exception that

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/errors.py in new_error_context(fmt_, *args, **kwargs)
583         from numba import config
584         tb = sys.exc_info()[2] if config.FULL_TRACEBACKS else None
--> 585         six.reraise(type(newerr), newerr, tb)
586
587

~/miniconda3/envs/numba3/lib/python3.7/site-packages/numba/six.py in reraise(tp, value, tb)
657         if value.__traceback__ is not tb:
658             raise value.with_traceback(tb)
--> 659         raise value
660
661 else:

LoweringError: Failed at nopython (nopython mode backend)
Cannot cast array(float64, 0d, C) to float64: %".417" = load {i8*, i8*, i64, i64, double*, [0 x i64], [0 x i64]}, {i8*, i8*, i64, i64, double*, [0 x i64], [0 x i64]}* %"$22.9"

File "<ipython-input-1-f6cc8d5fb861>", line 8:
def func(A, B, indices):
<source elided>
index = indices[i]
rv[..., index] = B[..., index]
^
[1] During: lowering "rv[$22.13] = $22.9" at <ipython-input-1-f6cc8d5fb861> (8)
-------------------------------------------------------------------------------
This should not have happened, a problem has occurred in Numba's internals.

Please report the error message and traceback, along with a minimal reproducer
at: https://github.com/numba/numba/issues/new

If more help is needed please feel free to speak to the Numba core developers
directly at: https://gitter.im/numba/numba

Thanks in advance for your help in improving Numba!

# Fixed code
def get_array_index_type(ary, idx):
    """
    Returns None or a tuple-3 for the types of the input array, index, and
    resulting type of ``array[index]``.

    Note: This is shared logic for ndarray getitem and setitem.
    """
    if not isinstance(ary, types.Buffer):
        return

    ndim = ary.ndim

    left_indices = []
    right_indices = []
    ellipsis_met = False
    advanced = False
    has_integer = False

    if not isinstance(idx, types.BaseTuple):
        idx = [idx]

    # Walk indices
    for ty in idx:
        if ty is types.ellipsis:
            if ellipsis_met:
                raise TypeError(
                    "only one ellipsis allowed in array index (got %s)" % (idx,)
                )
            ellipsis_met = True
        elif isinstance(ty, types.SliceType):
            pass
        elif isinstance(ty, types.Integer):
            # Normalize integer index
            ty = types.intp if ty.signed else types.uintp
            # Integer indexing removes the given dimension
            ndim -= 1
            has_integer = True
        elif (
            isinstance(ty, types.Array)
            and ty.ndim == 0
            and isinstance(ty.dtype, types.Integer)
        ):
            # 0-d array used as integer index
            ndim -= 1
            has_integer = True
        elif (
            isinstance(ty, types.Array)
            and ty.ndim == 1
            and isinstance(ty.dtype, (types.Integer, types.Boolean))
        ):
            if advanced or has_integer:
                # We don't support the complicated combination of
                # advanced indices (and integers are considered part
                # of them by Numpy).
                raise NotImplementedError("only one advanced index supported")
            advanced = True
        else:
            raise TypeError("unsupported array index type %s in %s" % (ty, idx))
        (right_indices if ellipsis_met else left_indices).append(ty)

    # Only Numpy arrays support advanced indexing
    if advanced and not isinstance(ary, types.Array):
        return

    # Check indices and result dimensionality
    all_indices = left_indices + right_indices
    if ellipsis_met:
        assert right_indices[0] is types.ellipsis
        del right_indices[0]

    n_indices = len(all_indices) - ellipsis_met
    if n_indices > ary.ndim:
        raise TypeError("cannot index %s with %d indices: %s" % (ary, n_indices, idx))
    if n_indices == ary.ndim and ndim == 0 and not ellipsis_met:
        # Full integer indexing => scalar result
        # (note if ellipsis is present, a 0-d view is returned instead)
        res = ary.dtype

    elif advanced:
        # Result is a copy
        res = ary.copy(ndim=ndim, layout="C", readonly=False)

    else:
        # Result is a view
        if ary.slice_is_copy:
            # Avoid view semantics when the original type creates a copy
            # when slicing.
            return

        # Infer layout
        layout = ary.layout

        def keeps_contiguity(ty, is_innermost):
            # A slice can only keep an array contiguous if it is the
            # innermost index and it is not strided
            return (
                ty is types.ellipsis
                or isinstance(ty, types.Integer)
                or (
                    is_innermost and isinstance(ty, types.SliceType) and not ty.has_step
                )
            )

        def check_contiguity(outer_indices):
            """
            Whether indexing with the given indices (from outer to inner in
            physical layout order) can keep an array contiguous.
            """
            for ty in outer_indices[:-1]:
                if not keeps_contiguity(ty, False):
                    return False
            if outer_indices and not keeps_contiguity(outer_indices[-1], True):
                return False
            return True

        if layout == "C":
            # Integer indexing on the left keeps the array C-contiguous
            if n_indices == ary.ndim:
                # If all indices are there, ellipsis's place is indifferent
                left_indices = left_indices + right_indices
                right_indices = []
            if right_indices:
                layout = "A"
            elif not check_contiguity(left_indices):
                layout = "A"
        elif layout == "F":
            # Integer indexing on the right keeps the array F-contiguous
            if n_indices == ary.ndim:
                # If all indices are there, ellipsis's place is indifferent
                right_indices = left_indices + right_indices
                left_indices = []
            if left_indices:
                layout = "A"
            elif not check_contiguity(right_indices[::-1]):
                layout = "A"

        if ndim == 0:
            # Implicitly convert to a scalar if the output ndim==0
            res = ary.dtype
        else:
            res = ary.copy(ndim=ndim, layout=layout)

    # Re-wrap indices
    if isinstance(idx, types.BaseTuple):
        idx = types.BaseTuple.from_types(all_indices)
    else:
        (idx,) = all_indices

    return Indexing(idx, res, advanced)