[pypy-commit] pypy default: Flow space: "raise x" now explicitly asserts that x is not a None

arigo pypy.commits at gmail.com
Fri Dec 16 07:56:27 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r89096:2fbea2e90463
Date: 2016-12-16 13:40 +0100
http://bitbucket.org/pypy/pypy/changeset/2fbea2e90463/

Log:	Flow space: "raise x" now explicitly asserts that x is not a None

diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -231,6 +231,12 @@
             v = graph.getreturnvar()
             if v.annotation is None:
                 self.setbinding(v, s_ImpossibleValue)
+            v = graph.exceptblock.inputargs[1]
+            if v.annotation is not None and v.annotation.can_be_none():
+                raise annmodel.AnnotatorError(
+                    "%r is found by annotation to possibly raise None, "
+                    "but the None was not suppressed by the flow space" %
+                        (graph,))
 
     def validate(self):
         """Check that the annotation results are valid"""
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -484,6 +484,9 @@
     def __init__(self, classdefs):
         self.classdefs = classdefs
 
+    def can_be_none(self):
+        return False
+
     def as_SomeInstance(self):
         return unionof(*[SomeInstance(cdef) for cdef in self.classdefs])
 
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -4652,6 +4652,17 @@
         assert ('string formatting requires a constant string/unicode'
                 in str(e.value))
 
+    def test_cannot_raise_none(self):
+        def f(x):
+            s = None
+            if x > 5:
+                s = ValueError()
+            raise s
+        a = self.RPythonAnnotator()
+        a.build_types(f, [int])
+        s_exc = a.binding(graphof(a, f).exceptblock.inputargs[1])
+        assert not s_exc.can_be_none()
+
 
 def g(n):
     return [0, 1, 2, n]
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -597,6 +597,8 @@
 
         Returns an FSException object whose w_value is an instance of w_type.
         """
+        from rpython.rlib.debug import ll_assert_not_none
+
         w_is_type = op.isinstance(w_arg1, const(type)).eval(self)
         if self.guessbool(w_is_type):
             # this is for all cases of the form (Class, something)
@@ -618,6 +620,7 @@
                                 "separate value")
                 raise Raise(const(exc))
             w_value = w_arg1
+        w_value = op.simple_call(const(ll_assert_not_none), w_value).eval(self)
         w_type = op.type(w_value).eval(self)
         return FSException(w_type, w_value)
 
diff --git a/rpython/rlib/debug.py b/rpython/rlib/debug.py
--- a/rpython/rlib/debug.py
+++ b/rpython/rlib/debug.py
@@ -11,7 +11,8 @@
 
 # Expose these here (public interface)
 from rpython.rtyper.debug import (
-    ll_assert, FatalError, fatalerror, fatalerror_notb, debug_print_traceback)
+    ll_assert, FatalError, fatalerror, fatalerror_notb, debug_print_traceback,
+    ll_assert_not_none)
 
 
 class DebugLog(list):
diff --git a/rpython/rtyper/debug.py b/rpython/rtyper/debug.py
--- a/rpython/rtyper/debug.py
+++ b/rpython/rtyper/debug.py
@@ -20,6 +20,26 @@
         hop.exception_cannot_occur()
         hop.genop('debug_assert', vlist)
 
+def ll_assert_not_none(x):
+    """assert x is not None"""
+    assert x, "ll_assert_not_none(%r)" % (x,)
+    return x
+
+class Entry(ExtRegistryEntry):
+    _about_ = ll_assert_not_none
+
+    def compute_result_annotation(self, s_x):
+        return s_x.nonnoneify()
+
+    def specialize_call(self, hop):
+        [v0] = hop.inputargs(hop.args_r[0])
+        assert isinstance(v0.concretetype, lltype.Ptr)
+        v1 = hop.genop('ptr_nonzero', [v0], resulttype=lltype.Bool)
+        hop.exception_cannot_occur()
+        cmsg = hop.inputconst(lltype.Void, "ll_assert_not_none failed")
+        hop.genop('debug_assert', [v1, cmsg])
+        return v0
+
 class FatalError(Exception):
     pass
 


More information about the pypy-commit mailing list