# Buggy code
def _lower_array_expr(lowerer, expr):
    """Lower an array expression built by RewriteArrayExprs."""
    expr_name = "__numba_array_expr_%s" % (hex(hash(expr)).replace("-", "_"))
    expr_filename = expr.loc.filename
    expr_var_list = expr.list_vars()
    # The expression may use a given variable several times, but we
    # should only create one parameter for it.
    expr_var_unique = sorted(set(expr_var_list), key=lambda var: var.name)

    # Arguments are the names external to the new closure
    expr_args = [var.name for var in expr_var_unique]

    # 1. Create an AST tree from the array expression.

    with _legalize_parameter_names(expr_var_unique) as expr_params:
        if hasattr(ast, "arg"):
            # Should be Python 3.x
            ast_args = [ast.arg(param_name, None) for param_name in expr_params]
        else:
            # Should be Python 2.x
            ast_args = [ast.Name(param_name, ast.Param()) for param_name in expr_params]
        # Parse a stub function to ensure the AST is populated with
        # reasonable defaults for the Python version.
        ast_module = ast.parse(
            "def {0}(): return".format(expr_name), expr_filename, "exec"
        )
        assert hasattr(ast_module, "body") and len(ast_module.body) == 1
        ast_fn = ast_module.body[0]
        ast_fn.args.args = ast_args
        ast_fn.body[0].value, namespace = _arr_expr_to_ast(expr.expr)
        ast.fix_missing_locations(ast_module)

    # 2. Compile the AST module and extract the Python function.
    code_obj = compile(ast_module, expr_filename, "exec")
    exec(code_obj, namespace)
    impl = namespace[expr_name]

    # 3. Now compile a ufunc using the Python function as kernel.

    context = lowerer.context
    builder = lowerer.builder
    outer_sig = expr.ty(*(lowerer.typeof(name) for name in expr_args))
    inner_sig_args = []
    for argty in outer_sig.args:
        if isinstance(argty, types.Optional):
            argty = argty.type
        if isinstance(argty, types.Array):
            inner_sig_args.append(argty.dtype)
        else:
            inner_sig_args.append(argty)
    inner_sig = outer_sig.return_type.dtype(*inner_sig_args)

    # Follow the Numpy error model.  Note this also allows e.g. vectorizing
    # division (issue #1223).
    flags = compiler.Flags()
    flags.set("error_model", "numpy")
    cres = context.compile_subroutine(
        builder, impl, inner_sig, flags=flags, caching=False
    )

    # Create kernel subclass calling our native function
    from numba.np import npyimpl

    class ExprKernel(npyimpl._Kernel):
        def generate(self, *args):
            arg_zip = zip(args, self.outer_sig.args, inner_sig.args)
            cast_args = [self.cast(val, inty, outty) for val, inty, outty in arg_zip]
            result = self.context.call_internal(
                builder, cres.fndesc, inner_sig, cast_args
            )
            return self.cast(result, inner_sig.return_type, self.outer_sig.return_type)

    args = [lowerer.loadvar(name) for name in expr_args]
    return npyimpl.numpy_ufunc_kernel(
        context, builder, outer_sig, args, ExprKernel, explicit_output=False
    )


# Traceback (AssertionError)
--------------------------------------------------------------------
AssertionError                     Traceback (most recent call last)
/anaconda3/lib/python3.7/site-packages/numba/core/errors.py in new_error_context(fmt_, *args, **kwargs)
800     try:
--> 801         yield
802     except NumbaError as e:

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower_block(self, block)
266                                    loc=self.loc, errcls_=defaulterrcls):
--> 267                 self.lower_inst(inst)
268         self.post_block(block)

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower_inst(self, inst)
363             ty = self.typeof(inst.target.name)
--> 364             val = self.lower_assign(ty, inst)
365             self.storevar(val, inst.target.name)

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower_assign(self, ty, inst)
537         elif isinstance(value, ir.Expr):
--> 538             return self.lower_expr(ty, value)
539

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower_expr(self, resty, expr)
1257         elif expr.op in self.context.special_ops:
-> 1258             res = self.context.special_ops[expr.op](self, expr)
1259             return res

/anaconda3/lib/python3.7/site-packages/numba/np/ufunc/array_exprs.py in _lower_array_expr(lowerer, expr)
340
--> 341     with _legalize_parameter_names(expr_var_unique) as expr_params:
342

/anaconda3/lib/python3.7/contextlib.py in __enter__(self)
111         try:
--> 112             return next(self.gen)
113         except StopIteration:

/anaconda3/lib/python3.7/site-packages/numba/np/ufunc/array_exprs.py in _legalize_parameter_names(var_list)
312         # Caller should ensure the names are unique
--> 313         assert new_name not in var_map
314         var_map[new_name] = var, old_name

AssertionError:

During handling of the above exception, another exception occurred:

LoweringError                      Traceback (most recent call last)
<ipython-input-5-10e1bfec8407> in <module>
13
14 x = 5
---> 15 f(x)

/anaconda3/lib/python3.7/site-packages/numba/core/dispatcher.py in _compile_for_args(self, *args, **kws)
418                     e.patch_message('\n'.join((str(e).rstrip(), help_msg)))
419             # ignore the FULL_TRACEBACKS config, this needs reporting!
--> 420             raise e
421
422     def inspect_llvm(self, signature=None):

/anaconda3/lib/python3.7/site-packages/numba/core/dispatcher.py in _compile_for_args(self, *args, **kws)
351                 argtypes.append(self.typeof_pyval(a))
352         try:
--> 353             return self.compile(tuple(argtypes))
354         except errors.ForceLiteralArg as e:
355             # Received request for compiler re-entry with the list of arguments

/anaconda3/lib/python3.7/site-packages/numba/core/compiler_lock.py in _acquire_compile_lock(*args, **kwargs)
30         def _acquire_compile_lock(*args, **kwargs):
31             with self:
---> 32                 return func(*args, **kwargs)
33         return _acquire_compile_lock
34

/anaconda3/lib/python3.7/site-packages/numba/core/dispatcher.py in compile(self, sig)
792             self._cache_misses[sig] += 1
793             try:
--> 794                 cres = self._compiler.compile(args, return_type)
795             except errors.ForceLiteralArg as e:
796                 def folded(args, kws):

/anaconda3/lib/python3.7/site-packages/numba/core/dispatcher.py in compile(self, args, return_type)
75
76     def compile(self, args, return_type):
---> 77         status, retval = self._compile_cached(args, return_type)
78         if status:
79             return retval

/anaconda3/lib/python3.7/site-packages/numba/core/dispatcher.py in _compile_cached(self, args, return_type)
89
90         try:
---> 91             retval = self._compile_core(args, return_type)
92         except errors.TypingError as e:
93             self._failed_cache[key] = e

/anaconda3/lib/python3.7/site-packages/numba/core/dispatcher.py in _compile_core(self, args, return_type)
107                                       args=args, return_type=return_type,
108                                       flags=flags, locals=self.locals,
--> 109                                       pipeline_class=self.pipeline_class)
110         # Check typing error if object mode is used
111         if cres.typing_error is not None and not flags.enable_pyobject:

/anaconda3/lib/python3.7/site-packages/numba/core/compiler.py in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library, pipeline_class)
566     pipeline = pipeline_class(typingctx, targetctx, library,
567                               args, return_type, flags, locals)
--> 568     return pipeline.compile_extra(func)
569
570

/anaconda3/lib/python3.7/site-packages/numba/core/compiler.py in compile_extra(self, func)
337         self.state.lifted = ()
338         self.state.lifted_from = None
--> 339         return self._compile_bytecode()
340
341     def compile_ir(self, func_ir, lifted=(), lifted_from=None):

/anaconda3/lib/python3.7/site-packages/numba/core/compiler.py in _compile_bytecode(self)
399         """
400         assert self.state.func_ir is None
--> 401         return self._compile_core()
402
403     def _compile_ir(self):

/anaconda3/lib/python3.7/site-packages/numba/core/compiler.py in _compile_core(self)
379                 self.state.status.fail_reason = e
380                 if is_final_pipeline:
--> 381                     raise e
382         else:
383             raise CompilerError("All available pipelines exhausted")

/anaconda3/lib/python3.7/site-packages/numba/core/compiler.py in _compile_core(self)
370             res = None
371             try:
--> 372                 pm.run(self.state)
373                 if self.state.cr is not None:
374                     break

/anaconda3/lib/python3.7/site-packages/numba/core/compiler_machinery.py in run(self, state)
339                     (self.pipeline_name, pass_desc)
340                 patched_exception = self._patch_error(msg, e)
--> 341                 raise patched_exception
342
343     def dependency_analysis(self):

/anaconda3/lib/python3.7/site-packages/numba/core/compiler_machinery.py in run(self, state)
330                 pass_inst = _pass_registry.get(pss).pass_inst
331                 if isinstance(pass_inst, CompilerPass):
--> 332                     self._runPass(idx, pass_inst, state)
333                 else:
334                     raise BaseException("Legacy pass in use")

/anaconda3/lib/python3.7/site-packages/numba/core/compiler_lock.py in _acquire_compile_lock(*args, **kwargs)
30         def _acquire_compile_lock(*args, **kwargs):
31             with self:
---> 32                 return func(*args, **kwargs)
33         return _acquire_compile_lock
34

/anaconda3/lib/python3.7/site-packages/numba/core/compiler_machinery.py in _runPass(self, index, pss, internal_state)
289             mutated |= check(pss.run_initialization, internal_state)
290         with SimpleTimer() as pass_time:
--> 291             mutated |= check(pss.run_pass, internal_state)
292         with SimpleTimer() as finalize_time:
293             mutated |= check(pss.run_finalizer, internal_state)

/anaconda3/lib/python3.7/site-packages/numba/core/compiler_machinery.py in check(func, compiler_state)
262
263         def check(func, compiler_state):
--> 264             mangled = func(compiler_state)
265             if mangled not in (True, False):
266                 msg = ("CompilerPass implementations should return True/False. "

/anaconda3/lib/python3.7/site-packages/numba/core/typed_passes.py in run_pass(self, state)
440
441         # TODO: Pull this out into the pipeline
--> 442         NativeLowering().run_pass(state)
443         lowered = state['cr']
444         signature = typing.signature(state.return_type, *state.args)

/anaconda3/lib/python3.7/site-packages/numba/core/typed_passes.py in run_pass(self, state)
368                 lower = lowering.Lower(targetctx, library, fndesc, interp,
369                                        metadata=metadata)
--> 370                 lower.lower()
371                 if not flags.no_cpython_wrapper:
372                     lower.create_cpython_wrapper(flags.release_gil)

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower(self)
177         if self.generator_info is None:
178             self.genlower = None
--> 179             self.lower_normal_function(self.fndesc)
180         else:
181             self.genlower = self.GeneratorLower(self)

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower_normal_function(self, fndesc)
225         # Init argument values
226         self.extract_function_arguments()
--> 227         entry_block_tail = self.lower_function_body()
228
229         # Close tail of entry block

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower_function_body(self)
251             bb = self.blkmap[offset]
252             self.builder.position_at_end(bb)
--> 253             self.lower_block(block)
254         self.post_lower()
255         return entry_block_tail

/anaconda3/lib/python3.7/site-packages/numba/core/lowering.py in lower_block(self, block)
265             with new_error_context('lowering "{inst}" at {loc}', inst=inst,
266                                    loc=self.loc, errcls_=defaulterrcls):
--> 267                 self.lower_inst(inst)
268         self.post_block(block)
269

/anaconda3/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

/anaconda3/lib/python3.7/site-packages/numba/core/errors.py in new_error_context(fmt_, *args, **kwargs)
806         newerr = errcls(e).add_context(_format_msg(fmt_, args, kwargs))
807         tb = sys.exc_info()[2] if numba.core.config.FULL_TRACEBACKS else None
--> 808         reraise(type(newerr), newerr, tb)
809
810

/anaconda3/lib/python3.7/site-packages/numba/core/utils.py in reraise(tp, value, tb)
78     if value.__traceback__ is not tb:
79         raise value.with_traceback(tb)
---> 80     raise value
81
82

LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)


File "<ipython-input-5-10e1bfec8407>", line 10:
def f(x):
<source elided>
for _ in range(2):
val =  arr * arr
^

[1] During: lowering "$30binary_multiply.4 = arrayexpr(expr=(<built-in function mul>, [Var(arr_2, <ipython-input-5-10e1bfec8407>:9), Var(arr.2, <ipython-input-5-10e1bfec8407>:9)]), ty=array(float64, 1d, C))" at <ipython-input-5-10e1bfec8407> (10)

# Fixed code
def _lower_array_expr(lowerer, expr):
    """Lower an array expression built by RewriteArrayExprs."""
    expr_name = "__numba_array_expr_%s" % (hex(hash(expr)).replace("-", "_"))
    expr_filename = expr.loc.filename
    expr_var_list = expr.list_vars()
    # The expression may use a given variable several times, but we
    # should only create one parameter for it.
    expr_var_unique = sorted(set(expr_var_list), key=lambda var: var.name)

    # Arguments are the names external to the new closure
    expr_args = [var.name for var in expr_var_unique]

    # 1. Create an AST tree from the array expression.
    with _legalize_parameter_names(expr_var_unique) as expr_params:
        ast_args = [ast.arg(param_name, None) for param_name in expr_params]
        # Parse a stub function to ensure the AST is populated with
        # reasonable defaults for the Python version.
        ast_module = ast.parse(
            "def {0}(): return".format(expr_name), expr_filename, "exec"
        )
        assert hasattr(ast_module, "body") and len(ast_module.body) == 1
        ast_fn = ast_module.body[0]
        ast_fn.args.args = ast_args
        ast_fn.body[0].value, namespace = _arr_expr_to_ast(expr.expr)
        ast.fix_missing_locations(ast_module)

    # 2. Compile the AST module and extract the Python function.
    code_obj = compile(ast_module, expr_filename, "exec")
    exec(code_obj, namespace)
    impl = namespace[expr_name]

    # 3. Now compile a ufunc using the Python function as kernel.

    context = lowerer.context
    builder = lowerer.builder
    outer_sig = expr.ty(*(lowerer.typeof(name) for name in expr_args))
    inner_sig_args = []
    for argty in outer_sig.args:
        if isinstance(argty, types.Optional):
            argty = argty.type
        if isinstance(argty, types.Array):
            inner_sig_args.append(argty.dtype)
        else:
            inner_sig_args.append(argty)
    inner_sig = outer_sig.return_type.dtype(*inner_sig_args)

    # Follow the Numpy error model.  Note this also allows e.g. vectorizing
    # division (issue #1223).
    flags = compiler.Flags()
    flags.set("error_model", "numpy")
    cres = context.compile_subroutine(
        builder, impl, inner_sig, flags=flags, caching=False
    )

    # Create kernel subclass calling our native function
    from numba.np import npyimpl

    class ExprKernel(npyimpl._Kernel):
        def generate(self, *args):
            arg_zip = zip(args, self.outer_sig.args, inner_sig.args)
            cast_args = [self.cast(val, inty, outty) for val, inty, outty in arg_zip]
            result = self.context.call_internal(
                builder, cres.fndesc, inner_sig, cast_args
            )
            return self.cast(result, inner_sig.return_type, self.outer_sig.return_type)

    args = [lowerer.loadvar(name) for name in expr_args]
    return npyimpl.numpy_ufunc_kernel(
        context, builder, outer_sig, args, ExprKernel, explicit_output=False
    )