Skip to content

Commit fd27a3d

Browse files
TeamTamoadyouknowone
authored andcommitted
Implement true hash for tuple
1 parent ad5ffb6 commit fd27a3d

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

Lib/test/test_tuple.py

-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ def f():
7777
# We expect tuples whose base components have deterministic hashes to
7878
# have deterministic hashes too - and, indeed, the same hashes across
7979
# platforms with hash codes of the same bit width.
80-
# TODO: RUSTPYTHON
81-
@unittest.expectedFailure
8280
def test_hash_exact(self):
8381
def check_one_exact(t, e32, e64):
8482
got = hash(t)

vm/src/builtins/tuple.rs

+38-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use super::{PositionIterInternal, PyGenericAlias, PyStrRef, PyType, PyTypeRef};
2-
use crate::common::{hash::PyHash, lock::PyMutex};
2+
use crate::common::{
3+
hash::{PyHash, PyUHash},
4+
lock::PyMutex,
5+
};
36
use crate::object::{Traverse, TraverseFn};
47
use crate::{
58
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
@@ -589,7 +592,38 @@ impl<T: TransmuteFromObject> ToPyObject for PyTupleTyped<T> {
589592
}
590593

591594
pub(super) fn tuple_hash(elements: &[PyObjectRef], vm: &VirtualMachine) -> PyResult<PyHash> {
592-
// TODO: See #3460 for the correct implementation.
593-
// https://github.com/RustPython/RustPython/pull/3460
594-
crate::utils::hash_iter(elements.iter(), vm)
595+
#[cfg(target_pointer_width = "64")]
596+
const PRIME1: PyUHash = 11400714785074694791;
597+
#[cfg(target_pointer_width = "64")]
598+
const PRIME2: PyUHash = 14029467366897019727;
599+
#[cfg(target_pointer_width = "64")]
600+
const PRIME5: PyUHash = 2870177450012600261;
601+
#[cfg(target_pointer_width = "64")]
602+
const ROTATE: u32 = 31;
603+
604+
#[cfg(target_pointer_width = "32")]
605+
const PRIME1: PyUHash = 2654435761;
606+
#[cfg(target_pointer_width = "32")]
607+
const PRIME2: PyUHash = 2246822519;
608+
#[cfg(target_pointer_width = "32")]
609+
const PRIME5: PyUHash = 374761393;
610+
#[cfg(target_pointer_width = "32")]
611+
const ROTATE: u32 = 13;
612+
613+
let mut acc = PRIME5;
614+
let len = elements.len() as PyUHash;
615+
616+
for val in elements {
617+
let lane = val.hash(vm)? as PyUHash;
618+
acc = acc.wrapping_add(lane.wrapping_mul(PRIME2));
619+
acc = acc.rotate_left(ROTATE);
620+
acc = acc.wrapping_mul(PRIME1);
621+
}
622+
623+
acc = acc.wrapping_add(len ^ (PRIME5 ^ 3527539));
624+
625+
if acc as PyHash == -1 {
626+
return Ok(1546275796);
627+
}
628+
Ok(acc as PyHash)
595629
}

0 commit comments

Comments
 (0)