Author: Romain Guillebert <romain...@gmail.com> Branch: Changeset: r66379:c240d50f3830 Date: 2013-08-28 13:37 +0100 http://bitbucket.org/pypy/pypy/changeset/c240d50f3830/
Log: Merge heads diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py --- a/rpython/annotator/annrpython.py +++ b/rpython/annotator/annrpython.py @@ -5,7 +5,7 @@ from rpython.tool.ansi_print import ansi_log from rpython.tool.pairtype import pair from rpython.tool.error import (format_blocked_annotation_error, - AnnotatorError, gather_error, ErrorWrapper) + AnnotatorError, gather_error, ErrorWrapper, source_lines) from rpython.flowspace.model import (Variable, Constant, FunctionGraph, c_last_exception, checkgraph) from rpython.translator import simplify, transform @@ -383,8 +383,8 @@ try: unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)] except annmodel.UnionError, e: - e.args = e.args + ( - ErrorWrapper(gather_error(self, graph, block, None)),) + # Add source code to the UnionError + e.source = '\n'.join(source_lines(graph, block, None, long=True)) raise # if the merged cells changed, we must redo the analysis if unions != oldcells: diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py --- a/rpython/annotator/binaryop.py +++ b/rpython/annotator/binaryop.py @@ -243,14 +243,16 @@ if t2 is int: if int2.nonneg == False: - raise UnionError, "Merging %s and a possibly negative int is not allowed" % t1 + raise UnionError(int1, int2, "RPython cannot prove that these " + \ + "integers are of the same signedness") knowntype = t1 elif t1 is int: if int1.nonneg == False: - raise UnionError, "Merging %s and a possibly negative int is not allowed" % t2 + raise UnionError(int1, int2, "RPython cannot prove that these " + \ + "integers are of the same signedness") knowntype = t2 else: - raise UnionError, "Merging these types (%s, %s) is not supported" % (t1, t2) + raise UnionError(int1, int2) return SomeInteger(nonneg=int1.nonneg and int2.nonneg, knowntype=knowntype) @@ -551,9 +553,9 @@ def union((tup1, tup2)): if len(tup1.items) != len(tup2.items): - raise UnionError("cannot take the union of a tuple of length %d " - "and a tuple of length %d" % (len(tup1.items), - len(tup2.items))) + raise UnionError(tup1, tup2, "RPython cannot unify tuples of " + "different length: %d versus %d" % \ + (len(tup1.items), len(tup2.items))) else: unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)] return SomeTuple(items = unions) @@ -726,7 +728,8 @@ else: basedef = ins1.classdef.commonbase(ins2.classdef) if basedef is None: - raise UnionError(ins1, ins2) + raise UnionError(ins1, ins2, "RPython cannot unify instances " + "with no common base class") flags = ins1.flags if flags: flags = flags.copy() @@ -768,7 +771,8 @@ def union((iter1, iter2)): s_cont = unionof(iter1.s_container, iter2.s_container) if iter1.variant != iter2.variant: - raise UnionError("merging incompatible iterators variants") + raise UnionError(iter1, iter2, + "RPython cannot unify incompatible iterator variants") return SomeIterator(s_cont, *iter1.variant) @@ -778,8 +782,7 @@ if (bltn1.analyser != bltn2.analyser or bltn1.methodname != bltn2.methodname or bltn1.s_self is None or bltn2.s_self is None): - raise UnionError("cannot merge two different builtin functions " - "or methods:\n %r\n %r" % (bltn1, bltn2)) + raise UnionError(bltn1, bltn2) s_self = unionof(bltn1.s_self, bltn2.s_self) return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname) @@ -976,8 +979,8 @@ class __extend__(pairtype(SomeAddress, SomeObject)): def union((s_addr, s_obj)): - raise UnionError, "union of address and anything else makes no sense" + raise UnionError(s_addr, s_obj) class __extend__(pairtype(SomeObject, SomeAddress)): def union((s_obj, s_addr)): - raise UnionError, "union of address and anything else makes no sense" + raise UnionError(s_obj, s_addr) diff --git a/rpython/annotator/listdef.py b/rpython/annotator/listdef.py --- a/rpython/annotator/listdef.py +++ b/rpython/annotator/listdef.py @@ -58,7 +58,7 @@ def merge(self, other): if self is not other: if getattr(TLS, 'no_side_effects_in_union', 0): - raise UnionError("merging list/dict items") + raise UnionError(self, other) if other.dont_change_any_more: if self.dont_change_any_more: diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -680,6 +680,33 @@ """Signals an suspicious attempt at taking the union of deeply incompatible SomeXxx instances.""" + def __init__(self, s_obj1, s_obj2, msg=None): + """ + This exception expresses the fact that s_obj1 and s_obj2 cannot be unified. + The msg paramter is appended to a generic message. This can be used to + give the user a little more information. + """ + self.s_obj1 = s_obj1 + self.s_obj2 = s_obj2 + self.msg = msg + self.source = None + + def __str__(self): + s = "\n\n" + + if self.msg is not None: + s += "%s\n\n" % self.msg + + s += "Offending annotations:\n" + s += "%s\n%s\n\n" % (self.s_obj1, self.s_obj2) + + if self.source is not None: + s += self.source + + return s + + def __repr__(self): + return str(self) def unionof(*somevalues): "The most precise SomeValue instance that contains all the values." 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 @@ -4023,6 +4023,81 @@ a = self.RPythonAnnotator() assert not a.build_types(fn, [int]).nonneg + def test_unionerror_attrs(self): + def f(x): + if x < 10: + return 1 + else: + return "bbb" + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + the_exc = exc.value + s_objs = set([type(the_exc.s_obj1), type(the_exc.s_obj2)]) + + assert s_objs == set([annmodel.SomeInteger, annmodel.SomeString]) + assert the_exc.msg == None # Check that this is a generic UnionError + + def test_unionerror_tuple_size(self): + def f(x): + if x < 10: + return (1, ) + else: + return (1, 2) + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert exc.value.msg == "RPython cannot unify tuples of different length: 2 versus 1" + + def test_unionerror_signedness(self): + def f(x): + if x < 10: + return r_uint(99) + else: + return -1 + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert exc.value.msg == ("RPython cannot prove that these integers are of " + "the same signedness") + + def test_unionerror_instance(self): + class A(object): pass + class B(object): pass + + def f(x): + if x < 10: + return A() + else: + return B() + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert exc.value.msg == ("RPython cannot unify instances with no common base class") + + def test_unionerror_iters(self): + + def f(x): + d = { 1 : "a", 2 : "b" } + if x < 10: + return d.iterkeys() + else: + return d.itervalues() + a = self.RPythonAnnotator() + + with py.test.raises(annmodel.UnionError) as exc: + a.build_types(f, [int]) + + assert exc.value.msg == ("RPython cannot unify incompatible iterator variants") + 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 @@ -24,8 +24,9 @@ self.frame = frame def __str__(self): - msg = ['-+' * 30] + msg = ["\n"] msg += map(str, self.args) + msg += [""] msg += source_lines(self.frame.graph, None, offset=self.frame.last_instr) return "\n".join(msg) @@ -293,7 +294,7 @@ _unsupported_ops = [ ('BINARY_POWER', "a ** b"), - ('BUILD_CLASS', 'creating new classes'), + ('BUILD_CLASS', 'defining classes inside functions'), ('EXEC_STMT', 'exec statement'), ('STOP_CODE', '???'), ('STORE_NAME', 'modifying globals'), diff --git a/rpython/tool/error.py b/rpython/tool/error.py --- a/rpython/tool/error.py +++ b/rpython/tool/error.py @@ -90,7 +90,7 @@ format_simple_call(annotator, oper, msg) else: oper = None - msg.append(" " + str(oper)) + msg.append(" %s\n" % str(oper)) msg += source_lines(graph, block, operindex, long=True) if oper is not None: if SHOW_ANNOTATIONS: @@ -106,7 +106,7 @@ def format_blocked_annotation_error(annotator, blocked_blocks): text = [] for block, (graph, index) in blocked_blocks.items(): - text.append('-+' * 30) + text.append('\n') text.append("Blocked block -- operation cannot succeed") text.append(gather_error(annotator, graph, block, index)) return '\n'.join(text) diff --git a/rpython/translator/goal/translate.py b/rpython/translator/goal/translate.py --- a/rpython/translator/goal/translate.py +++ b/rpython/translator/goal/translate.py @@ -246,17 +246,19 @@ tb = None if got_error: import traceback - errmsg = ["Error:\n"] + stacktrace_errmsg = ["Error:\n"] exc, val, tb = sys.exc_info() - errmsg.extend([" %s" % line for line in traceback.format_exception(exc, val, tb)]) + stacktrace_errmsg.extend([" %s" % line for line in traceback.format_tb(tb)]) + summary_errmsg = traceback.format_exception_only(exc, val) block = getattr(val, '__annotator_block', None) if block: class FileLike: def write(self, s): - errmsg.append(" %s" % s) - errmsg.append("Processing block:\n") + summary_errmsg.append(" %s" % s) + summary_errmsg.append("Processing block:\n") t.about(block, FileLike()) - log.ERROR(''.join(errmsg)) + log.info(''.join(stacktrace_errmsg)) + log.ERROR(''.join(summary_errmsg)) else: log.event('Done.') _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit