Skip to content

Commit 8f67d08

Browse files
committed
make hashes always the size of pointers; introduce Py_hash_t #9778
1 parent 6fb4575 commit 8f67d08

31 files changed

+137
-131
lines changed

Doc/c-api/object.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,20 @@ is considered sufficient for this determination.
247247
*NULL* on failure.
248248
249249
250-
.. c:function:: long PyObject_Hash(PyObject *o)
250+
.. c:function:: Py_hash_t PyObject_Hash(PyObject *o)
251251
252252
.. index:: builtin: hash
253253
254254
Compute and return the hash value of an object *o*. On failure, return ``-1``.
255255
This is the equivalent of the Python expression ``hash(o)``.
256256
257+
.. versionchanged:: 3.2
257258
258-
.. c:function:: long PyObject_HashNotImplemented(PyObject *o)
259+
The return type is now Py_hash_t. This is a signed integer the same size
260+
as Py_ssize_t.
261+
262+
263+
.. c:function:: Py_hash_t PyObject_HashNotImplemented(PyObject *o)
259264
260265
Set a :exc:`TypeError` indicating that ``type(o)`` is not hashable and return ``-1``.
261266
This function receives special treatment when stored in a ``tp_hash`` slot,

Doc/c-api/typeobj.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,10 @@ type objects) *must* have the :attr:`ob_size` field.
306306
An optional pointer to a function that implements the built-in function
307307
:func:`hash`.
308308

309-
The signature is the same as for :c:func:`PyObject_Hash`; it must return a C
310-
long. The value ``-1`` should not be returned as a normal return value; when an
311-
error occurs during the computation of the hash value, the function should set
312-
an exception and return ``-1``.
309+
The signature is the same as for :c:func:`PyObject_Hash`; it must return a
310+
value of the type Py_hash_t. The value ``-1`` should not be returned as a
311+
normal return value; when an error occurs during the computation of the hash
312+
value, the function should set an exception and return ``-1``.
313313

314314
This field can be set explicitly to :c:func:`PyObject_HashNotImplemented` to
315315
block inheritance of the hash method from a parent type. This is interpreted

Include/bytesobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ functions should be applied to nil objects.
2929

3030
typedef struct {
3131
PyObject_VAR_HEAD
32-
long ob_shash;
32+
Py_hash_t ob_shash;
3333
char ob_sval[1];
3434

3535
/* Invariants:

Include/datetime.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ extern "C" {
3434
typedef struct
3535
{
3636
PyObject_HEAD
37-
long hashcode; /* -1 when unknown */
37+
Py_hash_t hashcode; /* -1 when unknown */
3838
int days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
3939
int seconds; /* 0 <= seconds < 24*3600 is invariant */
4040
int microseconds; /* 0 <= microseconds < 1000000 is invariant */
@@ -51,7 +51,7 @@ typedef struct
5151
*/
5252
#define _PyTZINFO_HEAD \
5353
PyObject_HEAD \
54-
long hashcode; \
54+
Py_hash_t hashcode; \
5555
char hastzinfo; /* boolean flag */
5656

5757
/* No _PyDateTime_BaseTZInfo is allocated; it's just to have something

Include/dictobject.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,8 @@ meaning otherwise.
4848
#define PyDict_MINSIZE 8
4949

5050
typedef struct {
51-
/* Cached hash code of me_key. Note that hash codes are C longs.
52-
* We have to use Py_ssize_t instead because dict_popitem() abuses
53-
* me_hash to hold a search finger.
54-
*/
55-
Py_ssize_t me_hash;
51+
/* Cached hash code of me_key. */
52+
Py_hash_t me_hash;
5653
PyObject *me_key;
5754
PyObject *me_value;
5855
} PyDictEntry;
@@ -84,7 +81,7 @@ struct _dictobject {
8481
* setitem calls.
8582
*/
8683
PyDictEntry *ma_table;
87-
PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash);
84+
PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, Py_hash_t hash);
8885
PyDictEntry ma_smalltable[PyDict_MINSIZE];
8986
};
9087

@@ -116,14 +113,14 @@ PyAPI_FUNC(void) PyDict_Clear(PyObject *mp);
116113
PyAPI_FUNC(int) PyDict_Next(
117114
PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value);
118115
PyAPI_FUNC(int) _PyDict_Next(
119-
PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, long *hash);
116+
PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash);
120117
PyAPI_FUNC(PyObject *) PyDict_Keys(PyObject *mp);
121118
PyAPI_FUNC(PyObject *) PyDict_Values(PyObject *mp);
122119
PyAPI_FUNC(PyObject *) PyDict_Items(PyObject *mp);
123120
PyAPI_FUNC(Py_ssize_t) PyDict_Size(PyObject *mp);
124121
PyAPI_FUNC(PyObject *) PyDict_Copy(PyObject *mp);
125122
PyAPI_FUNC(int) PyDict_Contains(PyObject *mp, PyObject *key);
126-
PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, long hash);
123+
PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, Py_hash_t hash);
127124
PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
128125
PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp);
129126
PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp);

Include/object.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ typedef PyObject *(*getattrofunc)(PyObject *, PyObject *);
275275
typedef int (*setattrfunc)(PyObject *, char *, PyObject *);
276276
typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *);
277277
typedef PyObject *(*reprfunc)(PyObject *);
278-
typedef long (*hashfunc)(PyObject *);
278+
typedef Py_hash_t (*hashfunc)(PyObject *);
279279
typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
280280
typedef PyObject *(*getiterfunc) (PyObject *);
281281
typedef PyObject *(*iternextfunc) (PyObject *);
@@ -440,8 +440,8 @@ PyAPI_FUNC(PyObject *) _PyObject_NextNotImplemented(PyObject *);
440440
PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *);
441441
PyAPI_FUNC(int) PyObject_GenericSetAttr(PyObject *,
442442
PyObject *, PyObject *);
443-
PyAPI_FUNC(long) PyObject_Hash(PyObject *);
444-
PyAPI_FUNC(long) PyObject_HashNotImplemented(PyObject *);
443+
PyAPI_FUNC(Py_hash_t) PyObject_Hash(PyObject *);
444+
PyAPI_FUNC(Py_hash_t) PyObject_HashNotImplemented(PyObject *);
445445
PyAPI_FUNC(int) PyObject_IsTrue(PyObject *);
446446
PyAPI_FUNC(int) PyObject_Not(PyObject *);
447447
PyAPI_FUNC(int) PyCallable_Check(PyObject *);
@@ -470,8 +470,8 @@ PyAPI_FUNC(int) Py_ReprEnter(PyObject *);
470470
PyAPI_FUNC(void) Py_ReprLeave(PyObject *);
471471

472472
/* Helpers for hash functions */
473-
PyAPI_FUNC(long) _Py_HashDouble(double);
474-
PyAPI_FUNC(long) _Py_HashPointer(void*);
473+
PyAPI_FUNC(Py_hash_t) _Py_HashDouble(double);
474+
PyAPI_FUNC(Py_hash_t) _Py_HashPointer(void*);
475475

476476
/* Helper for passing objects to printf and the like */
477477
#define PyObject_REPR(obj) _PyUnicode_AsString(PyObject_Repr(obj))

Include/pyport.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Used in: PY_LONG_LONG
130130
_PyHash_Double in Objects/object.c. Numeric hashes are based on
131131
reduction modulo the prime 2**_PyHASH_BITS - 1. */
132132

133-
#if SIZEOF_LONG >= 8
133+
#if SIZEOF_VOID_P >= 8
134134
#define _PyHASH_BITS 61
135135
#else
136136
#define _PyHASH_BITS 31
@@ -177,6 +177,9 @@ typedef Py_intptr_t Py_ssize_t;
177177
# error "Python needs a typedef for Py_ssize_t in pyport.h."
178178
#endif
179179

180+
/* Py_hash_t is the same size as a pointer. */
181+
typedef Py_ssize_t Py_hash_t;
182+
180183
/* Largest possible value of size_t.
181184
SIZE_MAX is part of C99, so it might be defined on some
182185
platforms. If it is not defined, (size_t)-1 is a portable

Include/setobject.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@ no meaning otherwise.
2222
#define PySet_MINSIZE 8
2323

2424
typedef struct {
25-
/* Cached hash code of the key. Note that hash codes are C longs.
26-
* We have to use Py_ssize_t instead because set_pop() abuses
27-
* the hash field to hold a search finger.
28-
*/
29-
Py_ssize_t hash;
25+
/* Cached hash code of the key. */
26+
Py_hash_t hash;
3027
PyObject *key;
3128
} setentry;
3229

@@ -53,10 +50,10 @@ struct _setobject {
5350
* saves repeated runtime null-tests.
5451
*/
5552
setentry *table;
56-
setentry *(*lookup)(PySetObject *so, PyObject *key, long hash);
53+
setentry *(*lookup)(PySetObject *so, PyObject *key, Py_hash_t hash);
5754
setentry smalltable[PySet_MINSIZE];
5855

59-
long hash; /* only used by frozenset objects */
56+
Py_hash_t hash; /* only used by frozenset objects */
6057
PyObject *weakreflist; /* List of weak references */
6158
};
6259

@@ -93,7 +90,7 @@ PyAPI_FUNC(int) PySet_Clear(PyObject *set);
9390
PyAPI_FUNC(int) PySet_Contains(PyObject *anyset, PyObject *key);
9491
PyAPI_FUNC(int) PySet_Discard(PyObject *set, PyObject *key);
9592
PyAPI_FUNC(int) PySet_Add(PyObject *set, PyObject *key);
96-
PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash);
93+
PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash);
9794
PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set);
9895
PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
9996

Include/unicodeobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ typedef struct {
372372
PyObject_HEAD
373373
Py_ssize_t length; /* Length of raw Unicode data in buffer */
374374
Py_UNICODE *str; /* Raw Unicode buffer */
375-
long hash; /* Hash value; -1 if not set */
375+
Py_hash_t hash; /* Hash value; -1 if not set */
376376
int state; /* != 0 if interned. In this case the two
377377
* references from the dictionary to this object
378378
* are *not* counted in ob_refcnt. */

Include/weakrefobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct _PyWeakReference {
2727
/* A cache for wr_object's hash code. As usual for hashes, this is -1
2828
* if the hash code isn't known yet.
2929
*/
30-
long hash;
30+
Py_hash_t hash;
3131

3232
/* If wr_object is weakly referenced, wr_object has a doubly-linked NULL-
3333
* terminated list of weak references to it. These are the list pointers.

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ Extensions
9393

9494
- The Unicode database was updated to 6.0.0.
9595

96+
C-API
97+
-----
98+
99+
- Issue #9778: Hash values are now always the size of pointers. A new Py_hash_t
100+
type has been introduced.
101+
96102
Tools/Demos
97103
-----------
98104

Modules/_datetimemodule.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ delta_richcompare(PyObject *self, PyObject *other, int op)
18431843

18441844
static PyObject *delta_getstate(PyDateTime_Delta *self);
18451845

1846-
static long
1846+
static Py_hash_t
18471847
delta_hash(PyDateTime_Delta *self)
18481848
{
18491849
if (self->hashcode == -1) {
@@ -2777,11 +2777,11 @@ date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
27772777
/*
27782778
Borrowed from stringobject.c, originally it was string_hash()
27792779
*/
2780-
static long
2780+
static Py_hash_t
27812781
generic_hash(unsigned char *data, int len)
27822782
{
27832783
register unsigned char *p;
2784-
register long x;
2784+
register Py_hash_t x;
27852785

27862786
p = (unsigned char *) data;
27872787
x = *p << 7;
@@ -2797,7 +2797,7 @@ generic_hash(unsigned char *data, int len)
27972797

27982798
static PyObject *date_getstate(PyDateTime_Date *self);
27992799

2800-
static long
2800+
static Py_hash_t
28012801
date_hash(PyDateTime_Date *self)
28022802
{
28032803
if (self->hashcode == -1)
@@ -3246,7 +3246,7 @@ timezone_richcompare(PyDateTime_TimeZone *self,
32463246
return delta_richcompare(self->offset, other->offset, op);
32473247
}
32483248

3249-
static long
3249+
static Py_hash_t
32503250
timezone_hash(PyDateTime_TimeZone *self)
32513251
{
32523252
return delta_hash((PyDateTime_Delta *)self->offset);
@@ -3751,7 +3751,7 @@ time_richcompare(PyObject *self, PyObject *other, int op)
37513751
return result;
37523752
}
37533753

3754-
static long
3754+
static Py_hash_t
37553755
time_hash(PyDateTime_Time *self)
37563756
{
37573757
if (self->hashcode == -1) {
@@ -4640,7 +4640,7 @@ datetime_richcompare(PyObject *self, PyObject *other, int op)
46404640
return result;
46414641
}
46424642

4643-
static long
4643+
static Py_hash_t
46444644
datetime_hash(PyDateTime_DateTime *self)
46454645
{
46464646
if (self->hashcode == -1) {

Modules/_pickle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ _PyMemoTable_Lookup(PyMemoTable *self, PyObject *key)
486486
size_t mask = (size_t)self->mt_mask;
487487
PyMemoEntry *table = self->mt_table;
488488
PyMemoEntry *entry;
489-
long hash = (long)key >> 3;
489+
Py_hash_t hash = (Py_hash_t)key >> 3;
490490

491491
i = hash & mask;
492492
entry = &table[i];

Objects/bytesobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -868,12 +868,12 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
868868
return result;
869869
}
870870

871-
static long
871+
static Py_hash_t
872872
bytes_hash(PyBytesObject *a)
873873
{
874874
register Py_ssize_t len;
875875
register unsigned char *p;
876-
register long x;
876+
register Py_hash_t x;
877877

878878
if (a->ob_shash != -1)
879879
return a->ob_shash;

Objects/classobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,10 @@ method_repr(PyMethodObject *a)
263263
return result;
264264
}
265265

266-
static long
266+
static Py_hash_t
267267
method_hash(PyMethodObject *a)
268268
{
269-
long x, y;
269+
Py_hash_t x, y;
270270
if (a->im_self == NULL)
271271
x = PyObject_Hash(Py_None);
272272
else

Objects/codeobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,10 @@ code_richcompare(PyObject *self, PyObject *other, int op)
417417
return res;
418418
}
419419

420-
static long
420+
static Py_hash_t
421421
code_hash(PyCodeObject *co)
422422
{
423-
long h, h0, h1, h2, h3, h4, h5, h6;
423+
Py_hash_t h, h0, h1, h2, h3, h4, h5, h6;
424424
h0 = PyObject_Hash(co->co_name);
425425
if (h0 == -1) return -1;
426426
h1 = PyObject_Hash(co->co_code);

Objects/complexobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ complex_repr(PyComplexObject *v)
394394
return complex_format(v, 0, 'r');
395395
}
396396

397-
static long
397+
static Py_hash_t
398398
complex_hash(PyComplexObject *v)
399399
{
400400
unsigned long hashreal, hashimag, combined;
@@ -413,7 +413,7 @@ complex_hash(PyComplexObject *v)
413413
combined = hashreal + _PyHASH_IMAG * hashimag;
414414
if (combined == (unsigned long)-1)
415415
combined = (unsigned long)-2;
416-
return (long)combined;
416+
return (Py_hash_t)combined;
417417
}
418418

419419
/* This macro may return! */

Objects/descrobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -916,10 +916,10 @@ wrapper_richcompare(PyObject *a, PyObject *b, int op)
916916
return v;
917917
}
918918

919-
static long
919+
static Py_hash_t
920920
wrapper_hash(wrapperobject *wp)
921921
{
922-
int x, y;
922+
Py_hash_t x, y;
923923
x = _Py_HashPointer(wp->descr);
924924
if (x == -1)
925925
return -1;

0 commit comments

Comments
 (0)