Commits

Ronan Lamy committed bb3fa3d

Handle empty cells in flowspace:
don't explode if they are not actually used,
give a nice error message if they are.

Comments (0)

Files changed (2)

rpython/flowspace/flowcontext.py

         if closure is None:
             self.closure = []
         else:
-            self.closure = [const(c.cell_contents) for c in closure]
+            self.closure = list(closure)
         assert len(self.closure) == len(self.pycode.co_freevars)
 
     def init_locals_stack(self, code):
     LOOKUP_METHOD = LOAD_ATTR
 
     def LOAD_DEREF(self, varindex):
-        self.pushvalue(self.closure[varindex])
+        cell = self.closure[varindex]
+        try:
+            content = cell.cell_contents
+        except ValueError:
+            name = self.pycode.co_freevars[varindex]
+            raise FlowingError("Undefined closure variable '%s'" % name)
+        self.pushvalue(const(content))
 
     def STORE_FAST(self, varindex):
         w_newvalue = self.popvalue()

rpython/flowspace/test/test_objspace.py

         graph = self.codetest(f)
         assert 'getattr' in self.all_operations(graph)
 
+    def test_empty_cell_unused(self):
+        def test(flag):
+            if flag:
+                b = 5
+            def g():
+                if flag:
+                    return b
+                else:
+                    return 1
+            return g
+        g1 = test(False)
+        graph = self.codetest(g1)
+        assert not self.all_operations(graph)
+        g2 = test(True)
+        graph = self.codetest(g2)
+        assert not self.all_operations(graph)
+
+    def test_empty_cell_error(self):
+        def test(flag):
+            if not flag:
+                b = 5
+            def g():
+                if flag:
+                    return b
+                else:
+                    return 1
+            return g
+        g = test(True)
+        with py.test.raises(FlowingError) as excinfo:
+            graph = self.codetest(g)
+        assert "Undefined closure variable 'b'" in str(excinfo.value)
+
+
 DATA = {'x': 5,
         'y': 6}