Author: Armin Rigo <[email protected]>
Branch: no-silent-merging-of-int-types
Changeset: r74913:bdfb89396304
Date: 2014-12-14 17:41 +0100
http://bitbucket.org/pypy/pypy/changeset/bdfb89396304/

Log:    No longer silently merge different int types in RPython.

diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -176,31 +176,35 @@
     return newfunc
 
 class __extend__(pairtype(SomeInteger, SomeInteger)):
-    # unsignedness is considered a rare and contagious disease
 
     def union((int1, int2)):
-        if int1.unsigned == int2.unsigned:
-            knowntype = rarithmetic.compute_restype(int1.knowntype, 
int2.knowntype)
+        # Rules: int1 and int2 must be in one of the following two cases:
+        #  * int1 and int2 are the same type; or
+        #  * one of them is a constant 'int'.
+        # This rule is stricter than it used to be (Dec'14).
+        #
+        t1 = int1.knowntype
+        if t1 is bool:
+            t1 = int
+        t2 = int2.knowntype
+        if t2 is bool:
+            t2 = int
+        #
+        if t1 == t2:
+            knowntype = t1
+        elif (t1 in (int, rarithmetic.r_int) and
+              t2 in (int, rarithmetic.r_int)):
+            knowntype = rarithmetic.r_int
+        elif (t1 in (int, rarithmetic.r_int) and int1.is_constant()
+                        and long(t2(int1.const)) == int1.const):
+            knowntype = t2
+        elif (t2 in (int, rarithmetic.r_int) and int2.is_constant()
+                        and long(t1(int2.const)) == int2.const):
+            knowntype = t1
         else:
-            t1 = int1.knowntype
-            if t1 is bool:
-                t1 = int
-            t2 = int2.knowntype
-            if t2 is bool:
-                t2 = int
-
-            if t2 is int:
-                if int2.nonneg == False:
-                    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(int1, int2, "RPython cannot prove that 
these " + \
-                            "integers are of the same signedness")
-                knowntype = t2
-            else:
-                raise UnionError(int1, int2)
+            raise UnionError(int1, int2, "cannot merge two integers"
+                        " of different types; explicit casts are needed."
+                        " (exception: integer constants)")
         return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
                            knowntype=knowntype)
 
@@ -218,13 +222,13 @@
     inplace_truediv = truediv
 
     def sub((int1, int2)):
-        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        knowntype = pair(int1, int2).union().knowntype
         return SomeInteger(knowntype=knowntype)
     sub.can_only_throw = []
     sub_ovf = _clone(sub, [OverflowError])
 
     def and_((int1, int2)):
-        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        knowntype = pair(int1, int2).union().knowntype
         return SomeInteger(nonneg=int1.nonneg or int2.nonneg,
                            knowntype=knowntype)
     and_.can_only_throw = []
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
@@ -921,9 +921,7 @@
                 c = b
             return c
         a = self.RPythonAnnotator()
-        s = a.build_types(f, [r_uint, int])
-        assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
-
+        py.test.raises(annmodel.UnionError, a.build_types, f, [r_uint, int])
 
     def test_prebuilt_long_that_is_not_too_long(self):
         small_constant = 12L
@@ -4178,9 +4176,6 @@
         with py.test.raises(annmodel.UnionError) as exc:
             a.build_types(f, [int])
 
-        assert ("RPython cannot prove that these integers are of the "
-                "same signedness" in exc.value.msg)
-
     def test_unionerror_instance(self):
         class A(object): pass
         class B(object): pass
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -440,6 +440,7 @@
                 self.max_delta = 0.125 * env.get_total_memory()
 
             gc_increment_step = 
env.read_uint_from_env('PYPY_GC_INCREMENT_STEP')
+            gc_increment_step = intmask(gc_increment_step)
             if gc_increment_step > 0:
                 self.gc_increment_step = gc_increment_step
             else:
diff --git a/rpython/rtyper/lltypesystem/rdict.py 
b/rpython/rtyper/lltypesystem/rdict.py
--- a/rpython/rtyper/lltypesystem/rdict.py
+++ b/rpython/rtyper/lltypesystem/rdict.py
@@ -476,7 +476,7 @@
     i = i & MASK
     ENTRY = lltype.typeOf(d.entries).TO.OF
     entry = d.entries[i]
-    if not d.entries.everused(i):
+    if not d.entries.everused(intmask(i)):
         # a new entry that was never used before
         ll_assert(not valid, "valid but not everused")
         rc = d.resize_counter - 3
@@ -586,10 +586,10 @@
     entries = d.entries
     ENTRIES = lltype.typeOf(entries).TO
     direct_compare = not hasattr(ENTRIES, 'no_direct_compare')
-    mask = len(entries) - 1
-    i = r_uint(hash & mask)
+    mask = r_uint(len(entries) - 1)
+    i = r_uint(hash) & mask
     # do the first try before any looping
-    if entries.valid(i):
+    if entries.valid(intmask(i)):
         checkingkey = entries[i].key
         if direct_compare and checkingkey == key:
             return i   # found the entry
@@ -599,13 +599,14 @@
             found = d.keyeq(checkingkey, key)
             if d.paranoia:
                 if (entries != d.entries or
-                    not entries.valid(i) or entries[i].key != checkingkey):
+                         not entries.valid(intmask(i)) or
+                         entries[i].key != checkingkey):
                     # the compare did major nasty stuff to the dict: start over
                     return ll_dict_lookup(d, key, hash)
             if found:
                 return i   # found the entry
         freeslot = -1
-    elif entries.everused(i):
+    elif entries.everused(intmask(i)):
         freeslot = intmask(i)
     else:
         return i | HIGHEST_BIT # pristine entry -- lookup failed
@@ -619,11 +620,11 @@
         i = i & mask
         # keep 'i' as a signed number here, to consistently pass signed
         # arguments to the small helper methods.
-        if not entries.everused(i):
+        if not entries.everused(intmask(i)):
             if freeslot == -1:
                 freeslot = intmask(i)
             return r_uint(freeslot) | HIGHEST_BIT
-        elif entries.valid(i):
+        elif entries.valid(intmask(i)):
             checkingkey = entries[i].key
             if direct_compare and checkingkey == key:
                 return i
@@ -633,7 +634,8 @@
                 found = d.keyeq(checkingkey, key)
                 if d.paranoia:
                     if (entries != d.entries or
-                        not entries.valid(i) or entries[i].key != checkingkey):
+                            not entries.valid(intmask(i)) or
+                            entries[i].key != checkingkey):
                         # the compare did major nasty stuff to the dict:
                         # start over
                         return ll_dict_lookup(d, key, hash)
@@ -648,10 +650,10 @@
     # key is new, and the dictionary doesn't contain deleted entries.
     # It only finds the next free slot for the given hash.
     entries = d.entries
-    mask = len(entries) - 1
-    i = r_uint(hash & mask)
+    mask = r_uint(len(entries) - 1)
+    i = r_uint(hash) & mask
     perturb = r_uint(hash)
-    while entries.everused(i):
+    while entries.everused(intmask(i)):
         i = (i << 2) + i + perturb + 1
         i = i & mask
         perturb >>= PERTURB_SHIFT
diff --git a/rpython/rtyper/lltypesystem/rordereddict.py 
b/rpython/rtyper/lltypesystem/rordereddict.py
--- a/rpython/rtyper/lltypesystem/rordereddict.py
+++ b/rpython/rtyper/lltypesystem/rordereddict.py
@@ -717,8 +717,8 @@
     INDEXES = _ll_ptr_to_array_of(T)
     entries = d.entries
     indexes = lltype.cast_opaque_ptr(INDEXES, d.indexes)
-    mask = len(indexes) - 1
-    i = r_uint(hash & mask)
+    mask = r_uint(len(indexes) - 1)
+    i = r_uint(hash) & mask
     # do the first try before any looping
     ENTRIES = lltype.typeOf(entries).TO
     direct_compare = not hasattr(ENTRIES, 'no_direct_compare')
@@ -802,8 +802,8 @@
     # It only finds the next free slot for the given hash.
     INDEXES = _ll_ptr_to_array_of(T)
     indexes = lltype.cast_opaque_ptr(INDEXES, d.indexes)
-    mask = len(indexes) - 1
-    i = r_uint(hash & mask)
+    mask = r_uint(len(indexes) - 1)
+    i = r_uint(hash) & mask
     perturb = r_uint(hash)
     while rffi.cast(lltype.Signed, indexes[i]) != 0:
         i = (i << 2) + i + perturb + 1
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to