Author: Ronan Lamy <[email protected]>
Branch: anntype
Changeset: r80802:7528a6ef8224
Date: 2015-11-20 15:11 +0000
http://bitbucket.org/pypy/pypy/changeset/7528a6ef8224/

Log:    Discover constantness of exception types in more cases

diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -504,16 +504,15 @@
                             self.bookkeeper.getuniqueclassdef(case))
                     s_matching_exc = s_exception.intersection(s_case)
                     if s_matching_exc != s_ImpossibleValue:
-                        self.follow_raise_link(graph, link,
-                            constraints={link.last_exc_value:
-                                s_matching_exc.as_SomeInstance()})
+                        self.follow_raise_link(graph, link, s_matching_exc)
                     s_exception = s_exception.difference(s_case)
             else:
                 for link in exits:
                     if link.exitcase is None:
                         self.follow_link(graph, link, {})
                     else:
-                        self.follow_raise_link(graph, link, {})
+                        s_exception = 
self.bookkeeper.valueoftype(link.exitcase)
+                        self.follow_raise_link(graph, link, s_exception)
         else:
             if isinstance(block.exitswitch, Variable):
                 knowntypedata = getattr(block.exitswitch.annotation,
@@ -559,7 +558,7 @@
         self.links_followed[link] = True
         self.addpendingblock(graph, link.target, inputs_s)
 
-    def follow_raise_link(self, graph, link, constraints):
+    def follow_raise_link(self, graph, link, s_last_exc_value):
         v_last_exc_type = link.last_exception
         v_last_exc_value = link.last_exc_value
 
@@ -567,15 +566,13 @@
                 issubclass(link.exitcase, BaseException))
 
         assert v_last_exc_type and v_last_exc_value
-        s_last_exc_value = self.bookkeeper.valueoftype(link.exitcase)
+
         if isinstance(v_last_exc_value, Variable):
             self.setbinding(v_last_exc_value, s_last_exc_value)
 
         if isinstance(v_last_exc_type, Variable):
-            self.setbinding(v_last_exc_type, SomeTypeOf([v_last_exc_value]))
+            self.setbinding(v_last_exc_type, typeof([v_last_exc_value]))
 
-
-        ignore_link = False
         inputs_s = []
         renaming = defaultdict(list)
         for v_out, v_input in zip(link.args, link.target.inputargs):
@@ -586,19 +583,13 @@
                 s_out = typeof(renaming[v_last_exc_value])
                 if isinstance(v_last_exc_type, Constant):
                     s_out.const = v_last_exc_type.value
+                elif v_last_exc_type.annotation.is_constant():
+                    s_out.const = v_last_exc_type.annotation.const
                 inputs_s.append(s_out)
             else:
                 s_out = self.annotation(v_out)
-                if v_out in constraints:
-                    s_constraint = constraints[v_out]
-                    s_out = pair(s_out, s_constraint).improve()
-                    # ignore links that try to pass impossible values
-                    if s_out == s_ImpossibleValue:
-                        ignore_link = True
                 s_out = self.apply_renaming(s_out, renaming)
                 inputs_s.append(s_out)
-        if ignore_link:
-            return
 
         self.links_followed[link] = True
         self.addpendingblock(graph, link.target, inputs_s)
diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -141,13 +141,17 @@
 class SomeTypeOf(SomeType):
     """The type of a variable"""
     def __init__(self, args_v):
-        assert isinstance(args_v, list)
-        assert args_v
         self.is_type_of = args_v
 
 def typeof(args_v):
     if args_v:
-        return SomeTypeOf(args_v)
+        result = SomeTypeOf(args_v)
+        if len(args_v) == 1:
+            s_arg = args_v[0].annotation
+            if isinstance(s_arg, SomeException) and len(s_arg.classdefs) == 1:
+                cdef, = s_arg.classdefs
+                result.const = cdef.classdesc.pyobj
+        return result
     else:
         return SomeType()
 
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
@@ -698,6 +698,42 @@
         s = a.build_types(snippet.exc_deduction_our_excs_plus_others, [])
         assert isinstance(s, annmodel.SomeInteger)
 
+    def test_complex_exception_deduction(self):
+        class InternalError(Exception):
+            def __init__(self, msg):
+                self.msg = msg
+
+        class AppError(Exception):
+            def __init__(self, msg):
+                self.msg = msg
+        def apperror(msg):
+            return AppError(msg)
+
+        def f(string):
+            if not string:
+                raise InternalError('Empty string')
+            return string, None
+        def cleanup():
+            pass
+
+        def g(string):
+            try:
+                try:
+                    string, _ = f(string)
+                except ZeroDivisionError:
+                    raise apperror('ZeroDivisionError')
+                try:
+                    result, _ = f(string)
+                finally:
+                    cleanup()
+            except InternalError as e:
+                raise apperror(e.msg)
+            return result
+
+        a = self.RPythonAnnotator()
+        s_result = a.build_types(g, [str])
+        assert isinstance(s_result, annmodel.SomeString)
+
     def test_method_exception_specialization(self):
         def f(l):
             try:
@@ -708,8 +744,9 @@
         s = a.build_types(f, [[int]])
         graph = graphof(a, f)
         etype, evalue = graph.exceptblock.inputargs
-        assert evalue.annotation.classdef.shortname == 'IndexError'
-        #assert etype.annotation.const == IndexError
+        assert evalue.annotation.classdefs == {
+                a.bookkeeper.getuniqueclassdef(IndexError)}
+        assert etype.annotation.const == IndexError
 
     def test_operation_always_raising(self):
         def operation_always_raising(n):
@@ -1393,8 +1430,7 @@
         t.const = KeyError
         assert et.annotation == t
         s_ev = ev.annotation
-        assert (isinstance(s_ev, annmodel.SomeInstance) and
-                s_ev.classdef == a.bookkeeper.getuniqueclassdef(KeyError))
+        assert s_ev == a.bookkeeper.new_exception([KeyError])
 
     def test_reraiseAnything(self):
         def f(dic):
@@ -1410,8 +1446,7 @@
         t.const = KeyError  # IndexError ignored because 'dic' is a dict
         assert et.annotation == t
         s_ev = ev.annotation
-        assert (isinstance(s_ev, annmodel.SomeInstance) and
-                s_ev.classdef == a.bookkeeper.getuniqueclassdef(KeyError))
+        assert s_ev == a.bookkeeper.new_exception([KeyError])
 
     def test_exception_mixing(self):
         def h():
diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -445,6 +445,13 @@
     def rtyper_makekey(self):
         return self.__class__, self.classdef
 
+class __extend__(annmodel.SomeException):
+    def rtyper_makerepr(self, rtyper):
+        return self.as_SomeInstance().rtyper_makerepr(rtyper)
+
+    def rtyper_makekey(self):
+        return self.__class__, frozenset(self.classdefs)
+
 class __extend__(annmodel.SomeType):
     def rtyper_makerepr(self, rtyper):
         return get_type_repr(rtyper)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to