[pypy-commit] pypy const-correctness: Progress

amauryfa noreply at buildbot.pypy.org
Fri Sep 13 08:34:30 CEST 2013


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: const-correctness
Changeset: r66931:5d4e27857d0a
Date: 2013-09-11 00:19 +0200
http://bitbucket.org/pypy/pypy/changeset/5d4e27857d0a/

Log:	Progress

diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -874,9 +874,7 @@
 
 class __extend__(pairtype(SomePtr, SomePtr)):
     def union((p1, p2)):
-        assert p1.ll_ptrtype == p2.ll_ptrtype,("mixing of incompatible pointer types: %r, %r" %
-                                               (p1.ll_ptrtype, p2.ll_ptrtype))
-        return SomePtr(p1.ll_ptrtype)
+        return SomePtr(p1.ll_ptrtype.union(p2.ll_ptrtype))
 
 class __extend__(pairtype(SomePtr, SomeInteger)):
 
diff --git a/rpython/rlib/rdtoa.py b/rpython/rlib/rdtoa.py
--- a/rpython/rlib/rdtoa.py
+++ b/rpython/rlib/rdtoa.py
@@ -39,7 +39,7 @@
     )
 
 dg_strtod = rffi.llexternal(
-    '_PyPy_dg_strtod', [rffi.CCHARP, rffi.CCHARPP], rffi.DOUBLE,
+    '_PyPy_dg_strtod', [rffi.CONST_CCHARP, rffi.CCHARPP], rffi.DOUBLE,
     compilation_info=eci, sandboxsafe=True)
 
 dg_dtoa = rffi.llexternal(
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -636,7 +636,7 @@
         if len(ARGS) != len(args_v):
             raise TypeError("graph with %d args called with wrong func ptr type: %r" %(len(args_v), ARGS))
         for T, v in zip(ARGS, args_v):
-            if not lltype.isCompatibleType(T, v.concretetype):
+            if not lltype.isConvertibleFrom(T, v.concretetype):
                 raise TypeError("graph with %r args called with wrong func ptr type: %r" %
                                 (tuple([v.concretetype for v in args_v]), ARGS))
         frame = self.newsubframe(graph, args)
diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py
--- a/rpython/rtyper/lltypesystem/lltype.py
+++ b/rpython/rtyper/lltypesystem/lltype.py
@@ -103,7 +103,10 @@
     def __ne__(self, other):
         return not (self == other)
 
-    _is_compatible = __eq__
+    def _is_convertible_from(self, other):
+        if self == other:
+            return True
+        return remove_const(self) == other
 
     def __setattr__(self, attr, nvalue):
         try:
@@ -766,6 +769,15 @@
                          hints={'interior_ptr_type':True})
         return R
 
+    def union(self, other):
+        if self == other:
+            return self
+        if remove_const(self) == remove_const(other):
+            return add_const(self)
+        raise AssertionError(
+            "mixing of incompatible pointer types: %r, %r" % (self, other))
+
+
 class InteriorPtr(LowLevelType):
     def __init__(self, PARENTTYPE, TO, offsets):
         self.PARENTTYPE = PARENTTYPE
@@ -984,14 +996,29 @@
     "The same type as T, but with any top level const-qualifier removed."
     if isinstance(T, Ptr):
         return Ptr(remove_const(T.TO))
+    if not isinstance(T, (Array, Struct)):
+        return T
     if not T._hints.get('render_as_const'):
         return T
-    hints = T._hints.copy()
-    del hints['render_as_const']
     T2 = object.__new__(type(T))
     T2.__dict__.update(T.__dict__)
-    T2._hints = T2._hints.copy()
-    del T2._hints['render_as_const']
+    hints = T2._hints.copy()
+    del hints['render_as_const']
+    T2._hints = frozendict(hints)
+    return T2
+
+def add_const(T):
+    "The same type as T, but with any top level const-qualifier removed."
+    if isinstance(T, Ptr):
+        return Ptr(add_const(T.TO))
+    assert isinstance(T, (Array, Struct))
+    if T._hints.get('render_as_const'):
+        return T
+    T2 = object.__new__(type(T))
+    T2.__dict__.update(T.__dict__)
+    hints = T2._hints.copy()
+    hints['render_as_const'] = True
+    T2._hints = frozendict(hints)
     return T2
 
 def direct_fieldptr(structptr, fieldname):
@@ -1212,7 +1239,7 @@
             if isinstance(T1, ContainerType):
                 raise TypeError("cannot directly assign to container array items")
             T2 = typeOf(val)
-            if T2 != T1:
+            if not isConvertibleFrom(T1, T2):
                 from rpython.rtyper.lltypesystem import rffi
                 if T1 is rffi.VOIDP and isinstance(T2, Ptr):
                     # Any pointer is convertible to void*
@@ -1262,7 +1289,7 @@
             if len(args) != len(self._T.ARGS):
                 raise TypeError,"calling %r with wrong argument number: %r" % (self._T, args)
             for i, a, ARG in zip(range(len(self._T.ARGS)), args, self._T.ARGS):
-                if typeOf(a) != remove_const(ARG):
+                if not isConvertibleFrom(ARG, typeOf(a)):
                     # ARG could be Void
                     if ARG == Void:
                         try:
@@ -2134,8 +2161,8 @@
         raise ValueError("init_identity_hash(): not for varsized types")
     p._obj._hash_cache_ = intmask(value)
 
-def isCompatibleType(TYPE1, TYPE2):
-    return TYPE1._is_compatible(TYPE2)
+def isConvertibleFrom(TYPE1, TYPE2):
+    return TYPE1._is_convertible_from(TYPE2)
 
 def enforce(TYPE, value):
     return TYPE._enforce(value)
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -650,12 +650,14 @@
 CCHARP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True}))
 
 # const char *
-CONST_CCHARP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True,
-                                       'render_as_const': True}))
+CONST_CCHARP = lltype.add_const(CCHARP)
 
 # wchar_t *
 CWCHARP = lltype.Ptr(lltype.Array(lltype.UniChar, hints={'nolength': True}))
 
+# const wchar_t *
+CONST_CWCHARP = lltype.add_const(CWCHARP)
+
 # int *, unsigned int *, etc.
 #INTP = ...    see setup() above
 
@@ -684,6 +686,7 @@
         from rpython.rtyper.annlowlevel import llstr as llstrtype
         from rpython.rtyper.annlowlevel import hlstr as hlstrtype
         TYPEP = CCHARP
+        CONST_TYPEP = CONST_CCHARP
         ll_char_type = lltype.Char
         lastchar = '\x00'
         builder_class = StringBuilder
@@ -694,6 +697,7 @@
         from rpython.rtyper.annlowlevel import llunicode as llstrtype
         from rpython.rtyper.annlowlevel import hlunicode as hlstrtype
         TYPEP = CWCHARP
+        CONST_TYPEP = CONST_CWCHARP
         ll_char_type = lltype.UniChar
         lastchar = u'\x00'
         builder_class = UnicodeBuilder
@@ -710,7 +714,7 @@
         ll_s = llstrtype(s)
         copy_string_to_raw(ll_s, array, 0, i)
         array[i] = lastchar
-        return array
+        return cast(CONST_TYPEP, array)
     str2charp._annenforceargs_ = [strtype, bool]
 
     def free_charp(cp, track_allocation=True):
@@ -867,6 +871,7 @@
 
 # char**
 CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True}))
+CONST_CCHARPP = lltype.Ptr(lltype.Array(CONST_CCHARP, hints={'nolength': True}))
 
 def liststr2charpp(l):
     """ list[str] -> char**, NULL terminated
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -57,7 +57,7 @@
 
     def test_string(self):
         eci = ExternalCompilationInfo(includes=['string.h'])
-        z = llexternal('strlen', [CCHARP], Signed, compilation_info=eci)
+        z = llexternal('strlen', [CONST_CCHARP], Signed, compilation_info=eci)
 
         def f():
             s = str2charp("xxx")
@@ -70,7 +70,7 @@
 
     def test_unicode(self):
         eci = ExternalCompilationInfo(includes=['string.h'])
-        z = llexternal('wcslen', [CWCHARP], Signed, compilation_info=eci)
+        z = llexternal('wcslen', [CONST_CWCHARP], Signed, compilation_info=eci)
 
         def f():
             s = unicode2wcharp(u"xxx\xe9")
@@ -87,7 +87,7 @@
         #include <src/allocator.h>
         #include <src/mem.h>
 
-        char *f(char* arg)
+        char *f(const char* arg)
         {
             char *ret;
             /* lltype.free uses OP_RAW_FREE, we must allocate
@@ -99,8 +99,8 @@
         }
         """)
         eci = ExternalCompilationInfo(separate_module_sources=[c_source],
-                                      post_include_bits=['char *f(char*);'])
-        z = llexternal('f', [CCHARP], CCHARP, compilation_info=eci)
+                                      post_include_bits=['char *f(const char*);'])
+        z = llexternal('f', [CONST_CCHARP], CCHARP, compilation_info=eci)
 
         def f():
             s = str2charp("xxx")
@@ -117,7 +117,7 @@
         c_source = """
         #include <string.h>
 
-        int f(char *args[]) {
+        int f(const char *args[]) {
             char **p = args;
             int l = 0;
             while (*p) {
@@ -128,11 +128,11 @@
         }
         """
         eci = ExternalCompilationInfo(separate_module_sources=[c_source])
-        z = llexternal('f', [CCHARPP], Signed, compilation_info=eci)
+        z = llexternal('f', [CONST_CCHARPP], Signed, compilation_info=eci)
 
         def f():
             l = ["xxx", "x", "xxxx"]
-            ss = liststr2charpp(l)
+            ss = liststr2charpp(cast(CONST_CCHARPP, l))
             result = z(ss)
             free_charpp(ss)
             return result
@@ -617,14 +617,14 @@
 
     def test_stringpolicy1(self):
         eci = ExternalCompilationInfo(includes=['string.h'])
-        strlen = llexternal('strlen', [CCHARP], SIZE_T, compilation_info=eci)
+        strlen = llexternal('strlen', [CONST_CCHARP], SIZE_T, compilation_info=eci)
         def f():
             return cast(SIGNED, strlen("Xxx"))
         assert interpret(f, [], backendopt=True) == 3
 
     def test_stringpolicy3(self):
         eci = ExternalCompilationInfo(includes=['string.h'])
-        strlen = llexternal('strlen', [CCHARP], INT, compilation_info=eci)
+        strlen = llexternal('strlen', [CONST_CCHARP], INT, compilation_info=eci)
         def f():
             ll_str = str2charp("Xxx")
             res = strlen(ll_str)
@@ -635,7 +635,7 @@
 
     def test_stringpolicy_mixed(self):
         eci = ExternalCompilationInfo(includes=['string.h'])
-        strlen = llexternal('strlen', [CCHARP], SIZE_T,
+        strlen = llexternal('strlen', [CONST_CCHARP], SIZE_T,
                             compilation_info=eci)
         def f():
             res1 = strlen("abcd")
diff --git a/rpython/rtyper/module/ll_os_environ.py b/rpython/rtyper/module/ll_os_environ.py
--- a/rpython/rtyper/module/ll_os_environ.py
+++ b/rpython/rtyper/module/ll_os_environ.py
@@ -115,13 +115,13 @@
 def r_putenv(name, value):
     just_a_placeholder
 
-os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP,
+os_getenv = rffi.llexternal('getenv', [rffi.CONST_CCHARP], rffi.CCHARP,
                             threadsafe=False)
-os_putenv = rffi.llexternal('putenv', [rffi.CCHARP], rffi.INT)
+os_putenv = rffi.llexternal('putenv', [rffi.CONST_CCHARP], rffi.INT)
 if _WIN32:
-    _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP,
+    _wgetenv = rffi.llexternal('_wgetenv', [rffi.CONST_CWCHARP], rffi.CWCHARP,
                                compilation_info=eci, threadsafe=False)
-    _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT,
+    _wputenv = rffi.llexternal('_wputenv', [rffi.CONST_CWCHARP], rffi.INT,
                                compilation_info=eci)
 
 class EnvKeepalive:
diff --git a/rpython/rtyper/rmodel.py b/rpython/rtyper/rmodel.py
--- a/rpython/rtyper/rmodel.py
+++ b/rpython/rtyper/rmodel.py
@@ -3,7 +3,7 @@
 from rpython.rtyper.error import TyperError, MissingRTypeOperation
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.lltypesystem.lltype import (Void, Bool, Float, typeOf,
-    LowLevelType, isCompatibleType)
+    LowLevelType, isConvertibleFrom)
 from rpython.tool.pairtype import pairtype, extendabletype, pair
 
 
@@ -125,7 +125,7 @@
                 realtype = typeOf(value)
             except (AssertionError, AttributeError, TypeError):
                 realtype = '???'
-            if realtype != self.lowleveltype:
+            if realtype != lltype.remove_const(self.lowleveltype):
                 raise TyperError("convert_const(self = %r, value = %r)" % (
                     self, value))
         return value
@@ -400,7 +400,7 @@
             realtype = typeOf(value)
         except (AssertionError, AttributeError):
             realtype = '???'
-        if not isCompatibleType(realtype, lltype):
+        if not isConvertibleFrom(lltype, realtype):
             raise TyperError("inputconst(reqtype = %s, value = %s):\n"
                              "expected a %r,\n"
                              "     got a %r" % (reqtype, value,
diff --git a/rpython/translator/c/support.py b/rpython/translator/c/support.py
--- a/rpython/translator/c/support.py
+++ b/rpython/translator/c/support.py
@@ -66,7 +66,7 @@
         # check.  Something else will blow up instead, probably
         # very confusingly.
         if not is_pointer_to_forward_ref(ACTUAL_TYPE):
-            assert ACTUAL_TYPE == T
+            assert lltype.isConvertibleFrom(T, ACTUAL_TYPE)
         return c.value
 
 


More information about the pypy-commit mailing list