make hashes always the size of pointers; introduce Py_hash_t #9778
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index fc644f2..2b965c3 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -868,12 +868,12 @@
     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 afd4ec3..6df930f 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -263,10 +263,10 @@
     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 da5c09a..54c23ae 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -417,10 +417,10 @@
     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 674362f..c4ced31 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -394,7 +394,7 @@
     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 @@
     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 8a2ddfd..11418d1 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -916,10 +916,10 @@
     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 241790c..7fd586b 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -318,7 +318,7 @@
 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 @@
  * 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 @@
 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 @@
             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 @@
 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 @@
     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 @@
     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 @@
 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 @@
 PyObject *
 PyDict_GetItemWithError(PyObject *op, PyObject *key)
 {
-    long hash;
+    Py_hash_t hash;
     PyDictObject*mp = (PyDictObject *)op;
     PyDictEntry *ep;
 
@@ -796,7 +795,7 @@
 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 @@
 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 @@
 
 /* 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 @@
     *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 @@
 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 @@
         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 @@
         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 @@
                 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 @@
 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 @@
     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 @@
     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 @@
 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 @@
 static PyObject *
 dict_popitem(PyDictObject *mp)
 {
-    Py_ssize_t i = 0;
+    Py_hash_t i = 0;
     PyDictEntry *ep;
     PyObject *res;
 
@@ -2039,7 +2038,7 @@
 int
 PyDict_Contains(PyObject *op, PyObject *key)
 {
-    long hash;
+    Py_hash_t hash;
     PyDictObject *mp = (PyDictObject *)op;
     PyDictEntry *ep;
 
@@ -2055,7 +2054,7 @@
 
 /* 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 b792c19..d0173e8 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -522,7 +522,7 @@
     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 c9c9817..cf7eb2c 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -2552,7 +2552,7 @@
     return v;
 }
 
-static long
+static Py_hash_t
 long_hash(PyLongObject *v)
 {
     unsigned long x;
@@ -2606,7 +2606,7 @@
     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 356d161..f1a9f4b 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -224,10 +224,10 @@
     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 ff3363f..2f544ba 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -687,7 +687,7 @@
 
    */
 
-long
+Py_hash_t
 _Py_HashDouble(double v)
 {
     int e, sign;
@@ -730,24 +730,24 @@
     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 @@
     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 7eac1aa..54b14da 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -75,7 +75,7 @@
 */
 
 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 @@
  * 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 @@
 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 @@
 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 @@
         } else {
             /* ACTIVE */
             --i;
-            set_insert_clean(so, entry->key, (long) entry->hash);
+            set_insert_clean(so, entry->key, entry->hash);
         }
     }
 
@@ -369,7 +369,7 @@
     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 @@
 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 @@
 {       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 @@
 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 @@
 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 @@
     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 @@
     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 @@
     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 @@
 {
     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 @@
     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 @@
     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 @@
     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 @@
 }
 
 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 @@
     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 @@
     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 aa3be82..c55ad65 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -312,10 +312,10 @@
      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 faa03df..a3905d8 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -4918,13 +4918,12 @@
     }
 }
 
-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 @@
                         "__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 9fe9c42..0e2f950 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -7444,12 +7444,12 @@
 
 /* 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 f43b68d..7a2c1bd 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -139,7 +139,7 @@
 }
 
 
-static long
+static Py_hash_t
 weakref_hash(PyWeakReference *self)
 {
     if (self->hash != -1)