Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
make hashable the slice
  • Loading branch information
furkanonder committed Jan 23, 2023
commit ef22a9236526adc3e5bbd03f661814bb0cce61c0
6 changes: 2 additions & 4 deletions Lib/test/test_slice.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,8 @@ def test_repr(self):
self.assertEqual(repr(slice(1, 2, 3)), "slice(1, 2, 3)")

def test_hash(self):
# Verify clearing of SF bug #800796
self.assertRaises(TypeError, hash, slice(5))
with self.assertRaises(TypeError):
slice(5).__hash__()
self.assertEqual(hash(slice(5)), slice(5).__hash__())
self.assertNotEqual(slice(5), slice(6))

def test_cmp(self):
s1 = slice(1, 2, 3)
Expand Down
38 changes: 37 additions & 1 deletion Objects/sliceobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,42 @@ slice_traverse(PySliceObject *v, visitproc visit, void *arg)
return 0;
}

/* code based on tuplehash() of Objects/tupleobject.c */
#if SIZEOF_PY_UHASH_T > 4
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
#else
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
#endif

static Py_hash_t
slicehash(PySliceObject *v)
{
Py_uhash_t acc = _PyHASH_XXPRIME_5;
#define _PyHASH_SLICE_PART(com) { \
Py_uhash_t lane = PyObject_Hash(v->com); \
if(lane == (Py_uhash_t)-1) { \
return -1; \
} \
acc += lane * _PyHASH_XXPRIME_2; \
acc = _PyHASH_XXROTATE(acc); \
acc *= _PyHASH_XXPRIME_1; \
}
_PyHASH_SLICE_PART(start);
_PyHASH_SLICE_PART(stop);
_PyHASH_SLICE_PART(step);
#undef _PyHASH_SLICE_PART
if(acc == (Py_uhash_t)-1) {
return 1546275796;
}
return acc;
}

PyTypeObject PySlice_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"slice", /* Name of this type */
Expand All @@ -642,7 +678,7 @@ PyTypeObject PySlice_Type = {
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
PyObject_HashNotImplemented, /* tp_hash */
(hashfunc)slicehash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
Expand Down