Repository: serge-sans-paille/beniget

Issue:
Bug in nonlocal
```
def f():
    nonlocal f
    f = 2
    return f
f()
```

This code does not generate any warnings, while failing with `SyntaxError: no binding for nonlocal 'f' found`. 

Discussion:

Patch:
diff --git a/beniget/beniget.py b/beniget/beniget.py
index 9926bf2..ebd8e72 100644
--- a/beniget/beniget.py
+++ b/beniget/beniget.py
@@ -379,7 +379,7 @@ class DefUseChains(ast.NodeVisitor):
 
     def invalid_name_lookup(self, name, scope, precomputed_locals, local_defs):
         # We may hit the situation where we refer to a local variable which is
-        # not bound yet. This is a runtime error in Python, so we try to detec
+        # not bound yet. This is a runtime error in Python, so we try to detect
         # it statically.
 
         # not a local variable => fine
@@ -970,7 +970,9 @@ class DefUseChains(ast.NodeVisitor):
 
     def visit_Nonlocal(self, node):
         for name in node.names:
-            for d in reversed(self._definitions[:-1]):
+            # Exclude global scope
+            global_scope_depth = -self._scope_depths[0]
+            for d in reversed(self._definitions[global_scope_depth: -1]):
                 if name not in d:
                     continue
                 else:


Test patch:
diff --git a/tests/test_chains.py b/tests/test_chains.py
index 4f09d63..e03cd6d 100644
--- a/tests/test_chains.py
+++ b/tests/test_chains.py
@@ -523,6 +523,15 @@ def outer():
         code = "def A():\n x = 1\n class B: nonlocal x; x = x"
         self.check_message(code, [])
 
+    def test_unbound_local_identifier_nonlocal_points_to_global(self):
+        code = "def x():\n nonlocal x\n x = 1"
+        self.check_message(code,
+                           ["W: unbound identifier 'x' at <unknown>:2:1"])
+
+    def test_unbound_local_identifier_nonlocal_points_to_scoped_global(self):
+        code = "if 1:\n def x():\n  nonlocal x\n  x = 1"
+        self.check_message(code,
+                           ["W: unbound identifier 'x' at <unknown>:3:2"])
 
     def test_assign_uses_class_level_name(self):
         code = '''