diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 7efc0d2dcc7a8a..8410934423fae3 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -247,15 +247,20 @@ is considered sufficient for this determination. *NULL* on failure. -.. c:function:: long PyObject_Hash(PyObject *o) +.. c:function:: Py_hash_t PyObject_Hash(PyObject *o) .. index:: builtin: hash Compute and return the hash value of an object *o*. On failure, return ``-1``. This is the equivalent of the Python expression ``hash(o)``. + .. versionchanged:: 3.2 -.. c:function:: long PyObject_HashNotImplemented(PyObject *o) + The return type is now Py_hash_t. This is a signed integer the same size + as Py_ssize_t. + + +.. c:function:: Py_hash_t PyObject_HashNotImplemented(PyObject *o) Set a :exc:`TypeError` indicating that ``type(o)`` is not hashable and return ``-1``. This function receives special treatment when stored in a ``tp_hash`` slot, diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index a25ca41a45cc6b..fe751c21f2876d 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -306,10 +306,10 @@ type objects) *must* have the :attr:`ob_size` field. An optional pointer to a function that implements the built-in function :func:`hash`. - The signature is the same as for :c:func:`PyObject_Hash`; it must return a C - long. The value ``-1`` should not be returned as a normal return value; when an - error occurs during the computation of the hash value, the function should set - an exception and return ``-1``. + The signature is the same as for :c:func:`PyObject_Hash`; it must return a + value of the type Py_hash_t. The value ``-1`` should not be returned as a + normal return value; when an error occurs during the computation of the hash + value, the function should set an exception and return ``-1``. This field can be set explicitly to :c:func:`PyObject_HashNotImplemented` to block inheritance of the hash method from a parent type. This is interpreted diff --git a/Include/bytesobject.h b/Include/bytesobject.h index 916e3f7ce883d2..3c69d25b503444 100644 --- a/Include/bytesobject.h +++ b/Include/bytesobject.h @@ -29,7 +29,7 @@ functions should be applied to nil objects. typedef struct { PyObject_VAR_HEAD - long ob_shash; + Py_hash_t ob_shash; char ob_sval[1]; /* Invariants: diff --git a/Include/datetime.h b/Include/datetime.h index f472c421dcbded..2d71fced8dc6d3 100644 --- a/Include/datetime.h +++ b/Include/datetime.h @@ -34,7 +34,7 @@ extern "C" { typedef struct { PyObject_HEAD - long hashcode; /* -1 when unknown */ + Py_hash_t hashcode; /* -1 when unknown */ int days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */ int seconds; /* 0 <= seconds < 24*3600 is invariant */ int microseconds; /* 0 <= microseconds < 1000000 is invariant */ @@ -51,7 +51,7 @@ typedef struct */ #define _PyTZINFO_HEAD \ PyObject_HEAD \ - long hashcode; \ + Py_hash_t hashcode; \ char hastzinfo; /* boolean flag */ /* No _PyDateTime_BaseTZInfo is allocated; it's just to have something diff --git a/Include/dictobject.h b/Include/dictobject.h index 248192194921a6..024a688d2a9b52 100644 --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -48,11 +48,8 @@ meaning otherwise. #define PyDict_MINSIZE 8 typedef struct { - /* Cached hash code of me_key. Note that hash codes are C longs. - * We have to use Py_ssize_t instead because dict_popitem() abuses - * me_hash to hold a search finger. - */ - Py_ssize_t me_hash; + /* Cached hash code of me_key. */ + Py_hash_t me_hash; PyObject *me_key; PyObject *me_value; } PyDictEntry; @@ -84,7 +81,7 @@ struct _dictobject { * setitem calls. */ PyDictEntry *ma_table; - PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash); + PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, Py_hash_t hash); PyDictEntry ma_smalltable[PyDict_MINSIZE]; }; @@ -116,14 +113,14 @@ PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); PyAPI_FUNC(int) PyDict_Next( PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value); PyAPI_FUNC(int) _PyDict_Next( - PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, long *hash); + PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); PyAPI_FUNC(PyObject *) PyDict_Keys(PyObject *mp); PyAPI_FUNC(PyObject *) PyDict_Values(PyObject *mp); PyAPI_FUNC(PyObject *) PyDict_Items(PyObject *mp); PyAPI_FUNC(Py_ssize_t) PyDict_Size(PyObject *mp); PyAPI_FUNC(PyObject *) PyDict_Copy(PyObject *mp); PyAPI_FUNC(int) PyDict_Contains(PyObject *mp, PyObject *key); -PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, long hash); +PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, Py_hash_t hash); PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); diff --git a/Include/object.h b/Include/object.h index ef73a213d16f1e..f14fd07a04a2de 100644 --- a/Include/object.h +++ b/Include/object.h @@ -275,7 +275,7 @@ typedef PyObject *(*getattrofunc)(PyObject *, PyObject *); typedef int (*setattrfunc)(PyObject *, char *, PyObject *); typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *); typedef PyObject *(*reprfunc)(PyObject *); -typedef long (*hashfunc)(PyObject *); +typedef Py_hash_t (*hashfunc)(PyObject *); typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); typedef PyObject *(*getiterfunc) (PyObject *); typedef PyObject *(*iternextfunc) (PyObject *); @@ -440,8 +440,8 @@ PyAPI_FUNC(PyObject *) _PyObject_NextNotImplemented(PyObject *); PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *); PyAPI_FUNC(int) PyObject_GenericSetAttr(PyObject *, PyObject *, PyObject *); -PyAPI_FUNC(long) PyObject_Hash(PyObject *); -PyAPI_FUNC(long) PyObject_HashNotImplemented(PyObject *); +PyAPI_FUNC(Py_hash_t) PyObject_Hash(PyObject *); +PyAPI_FUNC(Py_hash_t) PyObject_HashNotImplemented(PyObject *); PyAPI_FUNC(int) PyObject_IsTrue(PyObject *); PyAPI_FUNC(int) PyObject_Not(PyObject *); PyAPI_FUNC(int) PyCallable_Check(PyObject *); @@ -470,8 +470,8 @@ PyAPI_FUNC(int) Py_ReprEnter(PyObject *); PyAPI_FUNC(void) Py_ReprLeave(PyObject *); /* Helpers for hash functions */ -PyAPI_FUNC(long) _Py_HashDouble(double); -PyAPI_FUNC(long) _Py_HashPointer(void*); +PyAPI_FUNC(Py_hash_t) _Py_HashDouble(double); +PyAPI_FUNC(Py_hash_t) _Py_HashPointer(void*); /* Helper for passing objects to printf and the like */ #define PyObject_REPR(obj) _PyUnicode_AsString(PyObject_Repr(obj)) diff --git a/Include/pyport.h b/Include/pyport.h index 5e98f0b8156dee..4331bf984451cd 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -130,7 +130,7 @@ Used in: PY_LONG_LONG _PyHash_Double in Objects/object.c. Numeric hashes are based on reduction modulo the prime 2**_PyHASH_BITS - 1. */ -#if SIZEOF_LONG >= 8 +#if SIZEOF_VOID_P >= 8 #define _PyHASH_BITS 61 #else #define _PyHASH_BITS 31 @@ -177,6 +177,9 @@ typedef Py_intptr_t Py_ssize_t; # error "Python needs a typedef for Py_ssize_t in pyport.h." #endif +/* Py_hash_t is the same size as a pointer. */ +typedef Py_ssize_t Py_hash_t; + /* Largest possible value of size_t. SIZE_MAX is part of C99, so it might be defined on some platforms. If it is not defined, (size_t)-1 is a portable diff --git a/Include/setobject.h b/Include/setobject.h index 574caf73803289..023c5fa7581825 100644 --- a/Include/setobject.h +++ b/Include/setobject.h @@ -22,11 +22,8 @@ no meaning otherwise. #define PySet_MINSIZE 8 typedef struct { - /* Cached hash code of the key. Note that hash codes are C longs. - * We have to use Py_ssize_t instead because set_pop() abuses - * the hash field to hold a search finger. - */ - Py_ssize_t hash; + /* Cached hash code of the key. */ + Py_hash_t hash; PyObject *key; } setentry; @@ -53,10 +50,10 @@ struct _setobject { * saves repeated runtime null-tests. */ setentry *table; - setentry *(*lookup)(PySetObject *so, PyObject *key, long hash); + setentry *(*lookup)(PySetObject *so, PyObject *key, Py_hash_t hash); setentry smalltable[PySet_MINSIZE]; - long hash; /* only used by frozenset objects */ + Py_hash_t hash; /* only used by frozenset objects */ PyObject *weakreflist; /* List of weak references */ }; @@ -93,7 +90,7 @@ PyAPI_FUNC(int) PySet_Clear(PyObject *set); PyAPI_FUNC(int) PySet_Contains(PyObject *anyset, PyObject *key); PyAPI_FUNC(int) PySet_Discard(PyObject *set, PyObject *key); PyAPI_FUNC(int) PySet_Add(PyObject *set, PyObject *key); -PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash); +PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash); PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set); PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index f61712bdbc6efe..42da8c338c94a9 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -372,7 +372,7 @@ typedef struct { PyObject_HEAD Py_ssize_t length; /* Length of raw Unicode data in buffer */ Py_UNICODE *str; /* Raw Unicode buffer */ - long hash; /* Hash value; -1 if not set */ + Py_hash_t hash; /* Hash value; -1 if not set */ int state; /* != 0 if interned. In this case the two * references from the dictionary to this object * are *not* counted in ob_refcnt. */ diff --git a/Include/weakrefobject.h b/Include/weakrefobject.h index f15c9d9c128365..b201d0814cc8f7 100644 --- a/Include/weakrefobject.h +++ b/Include/weakrefobject.h @@ -27,7 +27,7 @@ struct _PyWeakReference { /* A cache for wr_object's hash code. As usual for hashes, this is -1 * if the hash code isn't known yet. */ - long hash; + Py_hash_t hash; /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL- * terminated list of weak references to it. These are the list pointers. diff --git a/Misc/NEWS b/Misc/NEWS index 6ee769c387a5dc..fa3725a8da7a2e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -93,6 +93,12 @@ Extensions - The Unicode database was updated to 6.0.0. +C-API +----- + +- Issue #9778: Hash values are now always the size of pointers. A new Py_hash_t + type has been introduced. + Tools/Demos ----------- diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 9a04549787dd37..d791cdeca897b1 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1843,7 +1843,7 @@ delta_richcompare(PyObject *self, PyObject *other, int op) static PyObject *delta_getstate(PyDateTime_Delta *self); -static long +static Py_hash_t delta_hash(PyDateTime_Delta *self) { if (self->hashcode == -1) { @@ -2777,11 +2777,11 @@ date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw) /* Borrowed from stringobject.c, originally it was string_hash() */ -static long +static Py_hash_t generic_hash(unsigned char *data, int len) { register unsigned char *p; - register long x; + register Py_hash_t x; p = (unsigned char *) data; x = *p << 7; @@ -2797,7 +2797,7 @@ generic_hash(unsigned char *data, int len) static PyObject *date_getstate(PyDateTime_Date *self); -static long +static Py_hash_t date_hash(PyDateTime_Date *self) { if (self->hashcode == -1) @@ -3246,7 +3246,7 @@ timezone_richcompare(PyDateTime_TimeZone *self, return delta_richcompare(self->offset, other->offset, op); } -static long +static Py_hash_t timezone_hash(PyDateTime_TimeZone *self) { return delta_hash((PyDateTime_Delta *)self->offset); @@ -3751,7 +3751,7 @@ time_richcompare(PyObject *self, PyObject *other, int op) return result; } -static long +static Py_hash_t time_hash(PyDateTime_Time *self) { if (self->hashcode == -1) { @@ -4640,7 +4640,7 @@ datetime_richcompare(PyObject *self, PyObject *other, int op) return result; } -static long +static Py_hash_t datetime_hash(PyDateTime_DateTime *self) { if (self->hashcode == -1) { diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 61db7cd5cbbc6c..b810301cd58465 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -486,7 +486,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key) size_t mask = (size_t)self->mt_mask; PyMemoEntry *table = self->mt_table; PyMemoEntry *entry; - long hash = (long)key >> 3; + Py_hash_t hash = (Py_hash_t)key >> 3; i = hash & mask; entry = &table[i]; diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index fc644f24c06591..2b965c37aeda99 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -868,12 +868,12 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) return result; } -static long +static Py_hash_t bytes_hash(PyBytesObject *a) { register Py_ssize_t len; register unsigned char *p; - register long x; + register Py_hash_t x; if (a->ob_shash != -1) return a->ob_shash; diff --git a/Objects/classobject.c b/Objects/classobject.c index afd4ec3dc6ec2e..6df930fdcf629b 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -263,10 +263,10 @@ method_repr(PyMethodObject *a) return result; } -static long +static Py_hash_t method_hash(PyMethodObject *a) { - long x, y; + Py_hash_t x, y; if (a->im_self == NULL) x = PyObject_Hash(Py_None); else diff --git a/Objects/codeobject.c b/Objects/codeobject.c index da5c09ac8d276a..54c23aec36d9ee 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -417,10 +417,10 @@ code_richcompare(PyObject *self, PyObject *other, int op) return res; } -static long +static Py_hash_t code_hash(PyCodeObject *co) { - long h, h0, h1, h2, h3, h4, h5, h6; + Py_hash_t h, h0, h1, h2, h3, h4, h5, h6; h0 = PyObject_Hash(co->co_name); if (h0 == -1) return -1; h1 = PyObject_Hash(co->co_code); diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 674362f9ebcbad..c4ced31cb943e3 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -394,7 +394,7 @@ complex_repr(PyComplexObject *v) return complex_format(v, 0, 'r'); } -static long +static Py_hash_t complex_hash(PyComplexObject *v) { unsigned long hashreal, hashimag, combined; @@ -413,7 +413,7 @@ complex_hash(PyComplexObject *v) combined = hashreal + _PyHASH_IMAG * hashimag; if (combined == (unsigned long)-1) combined = (unsigned long)-2; - return (long)combined; + return (Py_hash_t)combined; } /* This macro may return! */ diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 8a2ddfd8a8a42e..11418d19e57bbf 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -916,10 +916,10 @@ wrapper_richcompare(PyObject *a, PyObject *b, int op) return v; } -static long +static Py_hash_t wrapper_hash(wrapperobject *wp) { - int x, y; + Py_hash_t x, y; x = _Py_HashPointer(wp->descr); if (x == -1) return -1; diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 241790ceba27d0..7fd586b3d99c30 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -318,7 +318,7 @@ the caller can (if it wishes) add the pair to the returned PyDictEntry*. */ static PyDictEntry * -lookdict(PyDictObject *mp, PyObject *key, register long hash) +lookdict(PyDictObject *mp, PyObject *key, register Py_hash_t hash) { register size_t i; register size_t perturb; @@ -407,7 +407,7 @@ lookdict(PyDictObject *mp, PyObject *key, register long hash) * This is valuable because dicts with only unicode keys are very common. */ static PyDictEntry * -lookdict_unicode(PyDictObject *mp, PyObject *key, register long hash) +lookdict_unicode(PyDictObject *mp, PyObject *key, register Py_hash_t hash) { register size_t i; register size_t perturb; @@ -527,7 +527,7 @@ Eats a reference to key and one to value. Returns -1 if an error occurred, or 0 on success. */ static int -insertdict(register PyDictObject *mp, PyObject *key, long hash, PyObject *value) +insertdict(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { PyObject *old_value; register PyDictEntry *ep; @@ -555,7 +555,7 @@ insertdict(register PyDictObject *mp, PyObject *key, long hash, PyObject *value) Py_DECREF(dummy); } ep->me_key = key; - ep->me_hash = (Py_ssize_t)hash; + ep->me_hash = hash; ep->me_value = value; mp->ma_used++; } @@ -571,7 +571,7 @@ Note that no refcounts are changed by this routine; if needed, the caller is responsible for incref'ing `key` and `value`. */ static void -insertdict_clean(register PyDictObject *mp, PyObject *key, long hash, +insertdict_clean(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) { register size_t i; @@ -590,7 +590,7 @@ insertdict_clean(register PyDictObject *mp, PyObject *key, long hash, assert(ep->me_value == NULL); mp->ma_fill++; ep->me_key = key; - ep->me_hash = (Py_ssize_t)hash; + ep->me_hash = hash; ep->me_value = value; mp->ma_used++; } @@ -667,8 +667,7 @@ dictresize(PyDictObject *mp, Py_ssize_t minused) for (ep = oldtable; i > 0; ep++) { if (ep->me_value != NULL) { /* active entry */ --i; - insertdict_clean(mp, ep->me_key, (long)ep->me_hash, - ep->me_value); + insertdict_clean(mp, ep->me_key, ep->me_hash, ep->me_value); } else if (ep->me_key != NULL) { /* dummy entry */ --i; @@ -713,7 +712,7 @@ _PyDict_NewPresized(Py_ssize_t minused) PyObject * PyDict_GetItem(PyObject *op, PyObject *key) { - long hash; + Py_hash_t hash; PyDictObject *mp = (PyDictObject *)op; PyDictEntry *ep; PyThreadState *tstate; @@ -763,7 +762,7 @@ PyDict_GetItem(PyObject *op, PyObject *key) PyObject * PyDict_GetItemWithError(PyObject *op, PyObject *key) { - long hash; + Py_hash_t hash; PyDictObject*mp = (PyDictObject *)op; PyDictEntry *ep; @@ -796,7 +795,7 @@ int PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value) { register PyDictObject *mp; - register long hash; + register Py_hash_t hash; register Py_ssize_t n_used; if (!PyDict_Check(op)) { @@ -842,7 +841,7 @@ int PyDict_DelItem(PyObject *op, PyObject *key) { register PyDictObject *mp; - register long hash; + register Py_hash_t hash; register PyDictEntry *ep; PyObject *old_value, *old_key; @@ -988,7 +987,7 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) /* Internal version of PyDict_Next that returns a hash value in addition to the key and value.*/ int -_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, long *phash) +_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, Py_hash_t *phash) { register Py_ssize_t i; register Py_ssize_t mask; @@ -1006,7 +1005,7 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, *ppos = i+1; if (i > mask) return 0; - *phash = (long)(ep[i].me_hash); + *phash = ep[i].me_hash; if (pkey) *pkey = ep[i].me_key; if (pvalue) @@ -1128,7 +1127,7 @@ static PyObject * dict_subscript(PyDictObject *mp, register PyObject *key) { PyObject *v; - long hash; + Py_hash_t hash; PyDictEntry *ep; assert(mp->ma_table != NULL); if (!PyUnicode_CheckExact(key) || @@ -1322,7 +1321,7 @@ dict_fromkeys(PyObject *cls, PyObject *args) PyObject *oldvalue; Py_ssize_t pos = 0; PyObject *key; - long hash; + Py_hash_t hash; if (dictresize(mp, Py_SIZE(seq))) return NULL; @@ -1340,7 +1339,7 @@ dict_fromkeys(PyObject *cls, PyObject *args) PyDictObject *mp = (PyDictObject *)d; Py_ssize_t pos = 0; PyObject *key; - long hash; + Py_hash_t hash; if (dictresize(mp, PySet_GET_SIZE(seq))) return NULL; @@ -1549,7 +1548,7 @@ PyDict_Merge(PyObject *a, PyObject *b, int override) Py_INCREF(entry->me_key); Py_INCREF(entry->me_value); if (insertdict(mp, entry->me_key, - (long)entry->me_hash, + entry->me_hash, entry->me_value) != 0) return -1; } @@ -1732,7 +1731,7 @@ dict_richcompare(PyObject *v, PyObject *w, int op) static PyObject * dict_contains(register PyDictObject *mp, PyObject *key) { - long hash; + Py_hash_t hash; PyDictEntry *ep; if (!PyUnicode_CheckExact(key) || @@ -1753,7 +1752,7 @@ dict_get(register PyDictObject *mp, PyObject *args) PyObject *key; PyObject *failobj = Py_None; PyObject *val = NULL; - long hash; + Py_hash_t hash; PyDictEntry *ep; if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj)) @@ -1782,7 +1781,7 @@ dict_setdefault(register PyDictObject *mp, PyObject *args) PyObject *key; PyObject *failobj = Py_None; PyObject *val = NULL; - long hash; + Py_hash_t hash; PyDictEntry *ep; if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj)) @@ -1818,7 +1817,7 @@ dict_clear(register PyDictObject *mp) static PyObject * dict_pop(PyDictObject *mp, PyObject *args) { - long hash; + Py_hash_t hash; PyDictEntry *ep; PyObject *old_value, *old_key; PyObject *key, *deflt = NULL; @@ -1864,7 +1863,7 @@ dict_pop(PyDictObject *mp, PyObject *args) static PyObject * dict_popitem(PyDictObject *mp) { - Py_ssize_t i = 0; + Py_hash_t i = 0; PyDictEntry *ep; PyObject *res; @@ -2039,7 +2038,7 @@ static PyMethodDef mapp_methods[] = { int PyDict_Contains(PyObject *op, PyObject *key) { - long hash; + Py_hash_t hash; PyDictObject *mp = (PyDictObject *)op; PyDictEntry *ep; @@ -2055,7 +2054,7 @@ PyDict_Contains(PyObject *op, PyObject *key) /* Internal version of PyDict_Contains used when the hash value is already known */ int -_PyDict_Contains(PyObject *op, PyObject *key, long hash) +_PyDict_Contains(PyObject *op, PyObject *key, Py_hash_t hash) { PyDictObject *mp = (PyDictObject *)op; PyDictEntry *ep; diff --git a/Objects/floatobject.c b/Objects/floatobject.c index b792c196e25c67..d0173e8d1340c1 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -522,7 +522,7 @@ float_richcompare(PyObject *v, PyObject *w, int op) return Py_NotImplemented; } -static long +static Py_hash_t float_hash(PyFloatObject *v) { return _Py_HashDouble(v->ob_fval); diff --git a/Objects/longobject.c b/Objects/longobject.c index c9c9817f12300f..cf7eb2c2b343c4 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2552,7 +2552,7 @@ long_richcompare(PyObject *self, PyObject *other, int op) return v; } -static long +static Py_hash_t long_hash(PyLongObject *v) { unsigned long x; @@ -2606,7 +2606,7 @@ long_hash(PyLongObject *v) x = x * sign; if (x == (unsigned long)-1) x = (unsigned long)-2; - return (long)x; + return (Py_hash_t)x; } diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 356d16184233c8..f1a9f4b7022d07 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -224,10 +224,10 @@ meth_richcompare(PyObject *self, PyObject *other, int op) return res; } -static long +static Py_hash_t meth_hash(PyCFunctionObject *a) { - long x,y; + Py_hash_t x, y; if (a->m_self == NULL) x = 0; else { diff --git a/Objects/object.c b/Objects/object.c index ff3363f43294cc..2f544ba67e0d49 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -687,7 +687,7 @@ PyObject_RichCompareBool(PyObject *v, PyObject *w, int op) */ -long +Py_hash_t _Py_HashDouble(double v) { int e, sign; @@ -730,24 +730,24 @@ _Py_HashDouble(double v) x = x * sign; if (x == (unsigned long)-1) x = (unsigned long)-2; - return (long)x; + return (Py_hash_t)x; } -long +Py_hash_t _Py_HashPointer(void *p) { - long x; + Py_hash_t x; size_t y = (size_t)p; /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid excessive hash collisions for dicts and sets */ y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4)); - x = (long)y; + x = (Py_hash_t)y; if (x == -1) x = -2; return x; } -long +Py_hash_t PyObject_HashNotImplemented(PyObject *v) { PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'", @@ -755,7 +755,7 @@ PyObject_HashNotImplemented(PyObject *v) return -1; } -long +Py_hash_t PyObject_Hash(PyObject *v) { PyTypeObject *tp = Py_TYPE(v); diff --git a/Objects/setobject.c b/Objects/setobject.c index 7eac1aa9c1e736..54b14da21c58e0 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -75,7 +75,7 @@ NULL if the rich comparison returns an error. */ static setentry * -set_lookkey(PySetObject *so, PyObject *key, register long hash) +set_lookkey(PySetObject *so, PyObject *key, register Py_hash_t hash) { register Py_ssize_t i; register size_t perturb; @@ -157,7 +157,7 @@ set_lookkey(PySetObject *so, PyObject *key, register long hash) * see if the comparison altered the table. */ static setentry * -set_lookkey_unicode(PySetObject *so, PyObject *key, register long hash) +set_lookkey_unicode(PySetObject *so, PyObject *key, register Py_hash_t hash) { register Py_ssize_t i; register size_t perturb; @@ -211,7 +211,7 @@ Used by the public insert routine. Eats a reference to key. */ static int -set_insert_key(register PySetObject *so, PyObject *key, long hash) +set_insert_key(register PySetObject *so, PyObject *key, Py_hash_t hash) { register setentry *entry; typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long); @@ -248,7 +248,7 @@ Note that no refcounts are changed by this routine; if needed, the caller is responsible for incref'ing `key`. */ static void -set_insert_clean(register PySetObject *so, PyObject *key, long hash) +set_insert_clean(register PySetObject *so, PyObject *key, Py_hash_t hash) { register size_t i; register size_t perturb; @@ -349,7 +349,7 @@ set_table_resize(PySetObject *so, Py_ssize_t minused) } else { /* ACTIVE */ --i; - set_insert_clean(so, entry->key, (long) entry->hash); + set_insert_clean(so, entry->key, entry->hash); } } @@ -369,7 +369,7 @@ set_add_entry(register PySetObject *so, setentry *entry) assert(so->fill <= so->mask); /* at least one empty slot */ n_used = so->used; Py_INCREF(key); - if (set_insert_key(so, key, (long) entry->hash) == -1) { + if (set_insert_key(so, key, entry->hash) == -1) { Py_DECREF(key); return -1; } @@ -381,7 +381,7 @@ set_add_entry(register PySetObject *so, setentry *entry) static int set_add_key(register PySetObject *so, PyObject *key) { - register long hash; + register Py_hash_t hash; register Py_ssize_t n_used; if (!PyUnicode_CheckExact(key) || @@ -410,7 +410,7 @@ set_discard_entry(PySetObject *so, setentry *oldentry) { register setentry *entry; PyObject *old_key; - entry = (so->lookup)(so, oldentry->key, (long) oldentry->hash); + entry = (so->lookup)(so, oldentry->key, oldentry->hash); if (entry == NULL) return -1; if (entry->key == NULL || entry->key == dummy) @@ -426,7 +426,7 @@ set_discard_entry(PySetObject *so, setentry *oldentry) static int set_discard_key(PySetObject *so, PyObject *key) { - register long hash; + register Py_hash_t hash; register setentry *entry; PyObject *old_key; @@ -675,7 +675,7 @@ set_merge(PySetObject *so, PyObject *otherset) static int set_contains_key(PySetObject *so, PyObject *key) { - long hash; + Py_hash_t hash; setentry *entry; if (!PyUnicode_CheckExact(key) || @@ -697,7 +697,7 @@ set_contains_entry(PySetObject *so, setentry *entry) PyObject *key; setentry *lu_entry; - lu_entry = (so->lookup)(so, entry->key, (long) entry->hash); + lu_entry = (so->lookup)(so, entry->key, entry->hash); if (lu_entry == NULL) return -1; key = lu_entry->key; @@ -761,11 +761,11 @@ set_traverse(PySetObject *so, visitproc visit, void *arg) return 0; } -static long +static Py_hash_t frozenset_hash(PyObject *self) { PySetObject *so = (PySetObject *)self; - long h, hash = 1927868237L; + Py_hash_t h, hash = 1927868237L; setentry *entry; Py_ssize_t pos = 0; @@ -926,7 +926,7 @@ set_update_internal(PySetObject *so, PyObject *other) if (PyDict_CheckExact(other)) { PyObject *value; Py_ssize_t pos = 0; - long hash; + Py_hash_t hash; Py_ssize_t dictsize = PyDict_Size(other); /* Do one big resize at the start, rather than @@ -1114,7 +1114,7 @@ set_swap_bodies(PySetObject *a, PySetObject *b) { Py_ssize_t t; setentry *u; - setentry *(*f)(PySetObject *so, PyObject *key, long hash); + setentry *(*f)(PySetObject *so, PyObject *key, Py_ssize_t hash); setentry tab[PySet_MINSIZE]; long h; @@ -1285,7 +1285,7 @@ set_intersection(PySetObject *so, PyObject *other) while ((key = PyIter_Next(it)) != NULL) { int rv; setentry entry; - long hash = PyObject_Hash(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { Py_DECREF(it); @@ -1442,7 +1442,7 @@ set_isdisjoint(PySetObject *so, PyObject *other) while ((key = PyIter_Next(it)) != NULL) { int rv; setentry entry; - long hash = PyObject_Hash(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { Py_DECREF(key); @@ -1641,7 +1641,7 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other) if (PyDict_CheckExact(other)) { PyObject *value; int rv; - long hash; + Py_hash_t hash; while (_PyDict_Next(other, &pos, &key, &value, &hash)) { setentry an_entry; @@ -2308,7 +2308,7 @@ PySet_Add(PyObject *anyset, PyObject *key) } int -_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash) +_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash) { setentry *entry; @@ -2319,7 +2319,7 @@ _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash) if (set_next((PySetObject *)set, pos, &entry) == 0) return 0; *key = entry->key; - *hash = (long) entry->hash; + *hash = entry->hash; return 1; } @@ -2363,7 +2363,7 @@ test_c_api(PySetObject *so) Py_ssize_t i; PyObject *elem=NULL, *dup=NULL, *t, *f, *dup2, *x; PyObject *ob = (PyObject *)so; - long hash; + Py_hash_t hash; PyObject *str; /* Verify preconditions */ diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index aa3be821bbe18a..c55ad65d9536e8 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -312,10 +312,10 @@ tuplerepr(PyTupleObject *v) 1330111, 1412633, 1165069, 1247599, 1495177, 1577699 */ -static long +static Py_hash_t tuplehash(PyTupleObject *v) { - register long x, y; + register Py_hash_t x, y; register Py_ssize_t len = Py_SIZE(v); register PyObject **p; long mult = 1000003L; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index faa03df6031641..a3905d84c709dc 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4918,13 +4918,12 @@ slot_tp_str(PyObject *self) } } -static long +static Py_hash_t slot_tp_hash(PyObject *self) { PyObject *func, *res; static PyObject *hash_str; - long h; - int overflow; + Py_ssize_t h; func = lookup_method(self, "__hash__", &hash_str); @@ -4947,20 +4946,20 @@ slot_tp_hash(PyObject *self) "__hash__ method should return an integer"); return -1; } - /* Transform the PyLong `res` to a C long `h`. For an existing - hashable Python object x, hash(x) will always lie within the range - of a C long. Therefore our transformation must preserve values - that already lie within this range, to ensure that if x.__hash__() - returns hash(y) then hash(x) == hash(y). */ - h = PyLong_AsLongAndOverflow(res, &overflow); - if (overflow) - /* res was not within the range of a C long, so we're free to + /* Transform the PyLong `res` to a Py_hash_t `h`. For an existing + hashable Python object x, hash(x) will always lie within the range of + Py_hash_t. Therefore our transformation must preserve values that + already lie within this range, to ensure that if x.__hash__() returns + hash(y) then hash(x) == hash(y). */ + h = PyLong_AsSsize_t(res); + if (h == -1 && PyErr_Occurred()) { + /* res was not within the range of a Py_hash_t, so we're free to use any sufficiently bit-mixing transformation; long.__hash__ will do nicely. */ + PyErr_Clear(); h = PyLong_Type.tp_hash(res); + } Py_DECREF(res); - if (h == -1 && !PyErr_Occurred()) - h = -2; return h; } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 9fe9c4279688bd..0e2f95018a5583 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7444,12 +7444,12 @@ unicode_getitem(PyUnicodeObject *self, Py_ssize_t index) /* Believe it or not, this produces the same value for ASCII strings as string_hash(). */ -static long +static Py_hash_t unicode_hash(PyUnicodeObject *self) { Py_ssize_t len; Py_UNICODE *p; - long x; + Py_hash_t x; if (self->hash != -1) return self->hash; diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index f43b68d607f733..7a2c1bda32375c 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -139,7 +139,7 @@ weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw) } -static long +static Py_hash_t weakref_hash(PyWeakReference *self) { if (self->hash != -1) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ece2a3728e8cc7..46045192cfdb58 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1148,12 +1148,12 @@ Delete a named attribute on an object; delattr(x, 'y') is equivalent to\n\ static PyObject * builtin_hash(PyObject *self, PyObject *v) { - long x; + Py_hash_t x; x = PyObject_Hash(v); if (x == -1) return NULL; - return PyLong_FromLong(x); + return PyLong_FromSsize_t(x); } PyDoc_STRVAR(hash_doc, diff --git a/Python/ceval.c b/Python/ceval.c index f85f33ad02ede3..1eb5f6204ba37f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2102,7 +2102,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Inline the PyDict_GetItem() calls. WARNING: this is an extreme speed hack. Do not try this at home. */ - long hash = ((PyUnicodeObject *)w)->hash; + Py_hash_t hash = ((PyUnicodeObject *)w)->hash; if (hash != -1) { PyDictObject *d; PyDictEntry *e; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 6c563f0d373b06..033c9d5e564122 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -567,7 +567,7 @@ get_hash_info(void) if (hash_info == NULL) return NULL; PyStructSequence_SET_ITEM(hash_info, field++, - PyLong_FromLong(8*sizeof(long))); + PyLong_FromLong(8*sizeof(Py_hash_t))); PyStructSequence_SET_ITEM(hash_info, field++, PyLong_FromLong(_PyHASH_MODULUS)); PyStructSequence_SET_ITEM(hash_info, field++,