Author: Ronan Lamy <ronan.l...@gmail.com> Branch: Changeset: r86451:eeb7fd8a6676 Date: 2016-08-23 16:27 +0100 http://bitbucket.org/pypy/pypy/changeset/eeb7fd8a6676/
Log: Make sure that hash(x) == x.__hash__() for int, long diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -362,11 +362,10 @@ return _new_int(space, w_inttype, w_x, w_base) def descr_hash(self, space): - # unlike CPython, we don't special-case the value -1 in most of - # our hash functions, so there is not much sense special-casing - # it here either. Make sure this is consistent with the hash of - # floats and longs. - return self.int(space) + # For compatibility with CPython, we special-case -1 + h = self.intval + h -= (h == -1) # No explicit condition, to avoid JIT bridges + return wrapint(space, h) def _int(self, space): return self.int(space) diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -130,7 +130,12 @@ descr_repr = _make_descr_unaryop('repr') descr_str = _make_descr_unaryop('str') - descr_hash = _make_descr_unaryop('hash') + + def descr_hash(self, space): + h = self.asbigint().hash() + h -= (h == -1) + return space.newint(h) + descr_oct = _make_descr_unaryop('oct') descr_hex = _make_descr_unaryop('hex') @@ -387,12 +392,12 @@ def _make_generic_descr_binop(opname): if opname not in COMMUTATIVE_OPS: raise Exception("Not supported") - + methname = opname + '_' if opname in ('and', 'or') else opname descr_rname = 'descr_r' + opname op = getattr(rbigint, methname) intop = getattr(rbigint, "int_" + methname) - + @func_renamer('descr_' + opname) def descr_binop(self, space, w_other): if isinstance(w_other, W_AbstractIntObject): @@ -412,7 +417,7 @@ return W_LongObject(op(w_other.asbigint(), self.num)) return descr_binop, descr_rbinop - + descr_add, descr_radd = _make_generic_descr_binop('add') descr_sub, descr_rsub = _make_generic_descr_binop_noncommutative('sub') descr_mul, descr_rmul = _make_generic_descr_binop('mul') @@ -454,12 +459,12 @@ except OverflowError: # b too big raise oefmt(space.w_OverflowError, "shift count too large") return W_LongObject(self.num.lshift(shift)) - + def _int_lshift(self, space, w_other): if w_other < 0: raise oefmt(space.w_ValueError, "negative shift count") return W_LongObject(self.num.lshift(w_other)) - + descr_lshift, descr_rlshift = _make_descr_binop(_lshift, _int_lshift) def _rshift(self, space, w_other): @@ -470,7 +475,7 @@ except OverflowError: # b too big # XXX maybe just return 0L instead? raise oefmt(space.w_OverflowError, "shift count too large") return newlong(space, self.num.rshift(shift)) - + def _int_rshift(self, space, w_other): if w_other < 0: raise oefmt(space.w_ValueError, "negative shift count") @@ -485,7 +490,7 @@ raise oefmt(space.w_ZeroDivisionError, "long division or modulo by zero") return newlong(space, z) - + def _floordiv(self, space, w_other): try: z = self.num.floordiv(w_other.asbigint()) @@ -505,7 +510,7 @@ raise oefmt(space.w_ZeroDivisionError, "long division or modulo by zero") return newlong(space, z) - + def _int_mod(self, space, w_other): try: z = self.num.int_mod(w_other) diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py --- a/pypy/objspace/std/test/test_intobject.py +++ b/pypy/objspace/std/test/test_intobject.py @@ -295,7 +295,11 @@ assert self.space.unwrap(result) == hex(x) -class AppTestInt: +class AppTestInt(object): + def test_hash(self): + assert hash(-1) == (-1).__hash__() == -2 + assert hash(-2) == (-2).__hash__() == -2 + def test_conjugate(self): assert (1).conjugate() == 1 assert (-1).conjugate() == -1 @@ -454,11 +458,11 @@ return None inst = a() raises(TypeError, int, inst) - assert inst.ar == True + assert inst.ar == True class b(object): - pass - raises((AttributeError,TypeError), int, b()) + pass + raises((AttributeError,TypeError), int, b()) def test_special_long(self): class a(object): diff --git a/pypy/objspace/std/test/test_longobject.py b/pypy/objspace/std/test/test_longobject.py --- a/pypy/objspace/std/test/test_longobject.py +++ b/pypy/objspace/std/test/test_longobject.py @@ -228,7 +228,7 @@ def test_hash(self): # ints have the same hash as equal longs for i in range(-4, 14): - assert hash(i) == hash(long(i)) + assert hash(i) == hash(long(i)) == long(i).__hash__() # might check too much -- it's ok to change the hashing algorithm assert hash(123456789L) == 123456789 assert hash(1234567890123456789L) in ( _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit