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