[pypy-commit] pypy default: make it an error to combine _immutable_ = True with quasi-immutable fields

cfbolz noreply at buildbot.pypy.org
Wed Aug 19 18:23:19 CEST 2015


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: 
Changeset: r79063:e889968fdd37
Date: 2015-08-19 18:05 +0200
http://bitbucket.org/pypy/pypy/changeset/e889968fdd37/

Log:	make it an error to combine _immutable_ = True with quasi-immutable
	fields

diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -616,26 +616,33 @@
                 while rbase.classdef is not None:
                     immutable_fields.update(rbase.immutable_field_set)
                     rbase = rbase.rbase
-                self._parse_field_list(immutable_fields, accessor)
+                self._parse_field_list(immutable_fields, accessor, hints)
 
-    def _parse_field_list(self, fields, accessor):
+    def _parse_field_list(self, fields, accessor, hints):
         ranking = {}
         for name in fields:
+            quasi = False
             if name.endswith('?[*]'):   # a quasi-immutable field pointing to
                 name = name[:-4]        # an immutable array
                 rank = IR_QUASIIMMUTABLE_ARRAY
+                quasi = True
             elif name.endswith('[*]'):    # for virtualizables' lists
                 name = name[:-3]
                 rank = IR_IMMUTABLE_ARRAY
             elif name.endswith('?'):    # a quasi-immutable field
                 name = name[:-1]
                 rank = IR_QUASIIMMUTABLE
+                quasi = True
             else:                       # a regular immutable/green field
                 rank = IR_IMMUTABLE
             try:
                 mangled_name, r = self._get_field(name)
             except KeyError:
                 continue
+            if quasi and hints.get("immutable"):
+                raise TyperError(
+                    "can't have _immutable_ = True and a quasi-immutable field "
+                    "%s in class %s" % (name, self.classdef))
             ranking[mangled_name] = rank
         accessor.initialize(self.object_type, ranking)
         return ranking
diff --git a/rpython/rtyper/test/test_rclass.py b/rpython/rtyper/test/test_rclass.py
--- a/rpython/rtyper/test/test_rclass.py
+++ b/rpython/rtyper/test/test_rclass.py
@@ -943,6 +943,19 @@
                 found.append(op.args[1].value)
         assert found == ['mutate_a', 'mutate_a', 'mutate_b']
 
+    def test_quasi_immutable_clashes_with_immutable(self):
+        from rpython.jit.metainterp.typesystem import deref
+        class A(object):
+            _immutable_ = True
+            _immutable_fields_ = ['a?']
+        def f():
+            a = A()
+            a.x = 42
+            a.a = 142
+            return A()
+        with py.test.raises(TyperError):
+            self.gengraph(f, [])
+
     def test_quasi_immutable_array(self):
         from rpython.jit.metainterp.typesystem import deref
         class A(object):


More information about the pypy-commit mailing list