Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r65997:e98d284a2cae
Date: 2013-08-07 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/e98d284a2cae/

Log:    Test and fix, giving a clearer error message (thanks krono).

diff --git a/rpython/annotator/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -391,6 +391,7 @@
     instance_level = False
     all_enforced_attrs = None   # or a set
     settled = False
+    _detect_invalid_attrs = None
 
     def __init__(self, bookkeeper, pyobj=None,
                  name=None, basedesc=None, classdict=None,
@@ -714,6 +715,10 @@
         # by changing the result's annotation (but not, of course, doing an
         # actual copy in the rtyper).  Tested in 
rpython.rtyper.test.test_rlist,
         # test_immutable_list_out_of_instance.
+        if self._detect_invalid_attrs and attr in self._detect_invalid_attrs:
+            raise Exception("field %r was migrated to %r from a subclass in "
+                            "which it was declared as _immutable_fields_" %
+                            (attr, self.pyobj))
         search1 = '%s[*]' % (attr,)
         search2 = '%s?[*]' % (attr,)
         cdesc = self
@@ -724,6 +729,14 @@
                     s_result.listdef.never_resize()
                     s_copy = s_result.listdef.offspring()
                     s_copy.listdef.mark_as_immutable()
+                    #
+                    cdesc = cdesc.basedesc
+                    while cdesc is not None:
+                        if cdesc._detect_invalid_attrs is None:
+                            cdesc._detect_invalid_attrs = set()
+                        cdesc._detect_invalid_attrs.add(attr)
+                        cdesc = cdesc.basedesc
+                    #
                     return s_copy
             cdesc = cdesc.basedesc
         return s_result     # common case
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
@@ -3717,6 +3717,24 @@
         a = self.RPythonAnnotator()
         a.build_types(f, [int])
 
+    def test_immutable_field_subclass(self):
+        class Root:
+            pass
+        class A(Root):
+            _immutable_fields_ = '_my_lst[*]'
+            def __init__(self, lst):
+                self._my_lst = lst
+        def foo(x):
+            return len(x._my_lst)
+
+        def f(n):
+            foo(A([2, n]))
+            foo(Root())
+
+        a = self.RPythonAnnotator()
+        e = py.test.raises(Exception, a.build_types, f, [int])
+        assert "field '_my_lst' was migrated" in str(e.value)
+
     def test_call_classes_with_noarg_init(self):
         class A:
             foo = 21
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to