Repository: numba/numba
Pull request: Enhance error message for undefined variables.
This patch traces back a temporary to its definition if type
inference fails to resolve a type for the temporary. This allows
a more informative error message to be emitted.

Fixes #2237

Problem statement:
Error message needs improvement
The error message when running this code:
``` python
from numba import jit
import numba
import numpy

f = numpy.zeros(shape=(3,3,3))

@jit(nopython=True)
def explorethisx(inar, x):
    places = []
    places.append((x,0))
    x1,y1 = x,0
    s = numba.int64(0)
    co = 0
    #for _ in range( 799):

    while co != numba.int16(799):
        co += 1
        a1,a2,a3 = 999,999,999
        a1 = inar[y1 + 1][x1-1][1]
        a2 = inar[y1 + 1][x1][1]
        a3 = inar[y1 + 1][x1 + 1][1]
        m = a1
        ch = -1
        if m > a2:
            m = a2
            ch = 0
        if m > a3:
            m = a3
            ch = 1
        x1 = x1 + ch
        y1 = y1 + 1
        s += inar[y1][x1][1]
        places.append((x1,y1))
    return [s, places]

print explorethisx(f,3)
```
does not indicate what line number the error is happening on, or what the problem is:
```
Traceback (most recent call last):
  File "test.py", line 35, in <module>
    print explorethisx(f,3)
  File "/Users/stan/anaconda/lib/python2.7/site-packages/numba/dispatcher.py", line 309, in _compile_for_args
    raise e
numba.errors.TypingError: Caused By:
Traceback (most recent call last):
  File "/Users/stan/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 228, in run
    stage()
  File "/Users/stan/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 442, in stage_nopython_frontend
    self.locals)
  File "/Users/stan/anaconda/lib/python2.7/site-packages/numba/compiler.py", line 795, in type_inference_stage
    typemap, restype, calltypes = infer.unify()
  File "/Users/stan/anaconda/lib/python2.7/site-packages/numba/typeinfer.py", line 819, in unify
    check_var(var)
  File "/Users/stan/anaconda/lib/python2.7/site-packages/numba/typeinfer.py", line 806, in check_var
    raise TypingError("Undefined variable '%s'" % (var,))
TypingError: Undefined variable '$313.3'

Failed at nopython (nopython frontend)
Undefined variable '$313.3'
```

Hints from issue discussion:
An identical issue has been posted as [question on StackOverflow](http://stackoverflow.com/q/41558683/5393381) today.

Just in case you're wondering what caused this: It's because of the shape-mismatch inside the `return [s, places]`.

A minimal example to reproduce the issue is

```
from numba import jit

@jit(nopython=True)
def test():
    return [1, [1,2]]

test()
```

Commit message: Enhance error message for undefined variables.

This patch traces back a temporary to its definition if type
inference fails to resolve a type for the temporary. This allows
a more informative error message to be emitted.

Fixes #2237

Patch to review:
diff --git a/numba/typeinfer.py b/numba/typeinfer.py
index 73e78175ecf..5c44110c68c 100644
--- a/numba/typeinfer.py
+++ b/numba/typeinfer.py
@@ -882,7 +882,21 @@ def unify(self):
         def check_var(name):
             tv = self.typevars[name]
             if not tv.defined:
-                raise TypingError("Undefined variable '%s'" % (var,))
+                def find_offender(name):
+                    """
+                    finds the offending variable definition to allow its
+                    inclusion in an error message
+                    """
+                    for block in self.func_ir.blocks.values():
+                        for x in block.find_insts(ir.Assign):
+                            if x.target.name == name:
+                                return x
+                    return None
+                offender = find_offender(var)
+                val = getattr(offender, 'value', 'unknown operation')
+                loc = getattr(offender, 'loc', 'unknown location')
+                msg = "Undefined variable '%s', operation: %s, location: %s"
+                raise TypingError(msg % (var, val, loc))
             tp = tv.getone()
             if not tp.is_precise():
                 raise TypingError("Can't infer type of variable '%s': %s" % (var, tp))


Code review comments:
diff_hunk: @@ -882,7 +882,21 @@ def unify(self):
         def check_var(name):
             tv = self.typevars[name]
             if not tv.defined:
-                raise TypingError("Undefined variable '%s'" % (var,))
+                def find_offender(name):
+                    """
+                    finds the offending variable definition to allow its
+                    inclusion in an error message
+                    """
+                    for block in self.func_ir.blocks.values():
path: numba/typeinfer.py
text: @user1:
There are some methods under class Block that you can use.  See  https://github.com/numba/numba/blob/b6b965afaf88594c1f754c9db07f3cf73b824478/numba/ir.py#L738-L755

Maybe, this function can be a method in Block, too.

@author:
I think it's a good idea to have it as a method on `Block`, might help with other error message handling. Will patch.