mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Implement true hash for tuple (#3460)
This commit is contained in:
2
Lib/test/test_tuple.py
vendored
2
Lib/test/test_tuple.py
vendored
@@ -77,8 +77,6 @@ class TupleTest(seq_tests.CommonTest):
|
||||
# We expect tuples whose base components have deterministic hashes to
|
||||
# have deterministic hashes too - and, indeed, the same hashes across
|
||||
# platforms with hash codes of the same bit width.
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_hash_exact(self):
|
||||
def check_one_exact(t, e32, e64):
|
||||
got = hash(t)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use super::{PositionIterInternal, PyGenericAlias, PyStrRef, PyType, PyTypeRef};
|
||||
use crate::common::{hash::PyHash, lock::PyMutex};
|
||||
use crate::common::{
|
||||
hash::{PyHash, PyUHash},
|
||||
lock::PyMutex,
|
||||
};
|
||||
use crate::object::{Traverse, TraverseFn};
|
||||
use crate::{
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
|
||||
@@ -589,7 +592,38 @@ impl<T: TransmuteFromObject> ToPyObject for PyTupleTyped<T> {
|
||||
}
|
||||
|
||||
pub(super) fn tuple_hash(elements: &[PyObjectRef], vm: &VirtualMachine) -> PyResult<PyHash> {
|
||||
// TODO: See #3460 for the correct implementation.
|
||||
// https://github.com/RustPython/RustPython/pull/3460
|
||||
crate::utils::hash_iter(elements.iter(), vm)
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const PRIME1: PyUHash = 11400714785074694791;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const PRIME2: PyUHash = 14029467366897019727;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const PRIME5: PyUHash = 2870177450012600261;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const ROTATE: u32 = 31;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const PRIME1: PyUHash = 2654435761;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const PRIME2: PyUHash = 2246822519;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const PRIME5: PyUHash = 374761393;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const ROTATE: u32 = 13;
|
||||
|
||||
let mut acc = PRIME5;
|
||||
let len = elements.len() as PyUHash;
|
||||
|
||||
for val in elements {
|
||||
let lane = val.hash(vm)? as PyUHash;
|
||||
acc = acc.wrapping_add(lane.wrapping_mul(PRIME2));
|
||||
acc = acc.rotate_left(ROTATE);
|
||||
acc = acc.wrapping_mul(PRIME1);
|
||||
}
|
||||
|
||||
acc = acc.wrapping_add(len ^ (PRIME5 ^ 3527539));
|
||||
|
||||
if acc as PyHash == -1 {
|
||||
return Ok(1546275796);
|
||||
}
|
||||
Ok(acc as PyHash)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user