Skip to content

Commit aa275ba

Browse files
committed
Fix usize not using the same hash as PyInt when used as key into a dictionary
1 parent 301c32d commit aa275ba

File tree

3 files changed

+16
-2
lines changed

3 files changed

+16
-2
lines changed

common/src/hash.rs

+5
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ pub fn hash_pointer(value: usize) -> PyHash {
8686
hash as _
8787
}
8888

89+
#[inline]
90+
pub fn hash_integer<T: num_traits::PrimInt>(data: T) -> PyHash {
91+
fix_sentinel(mod_int(data.to_i64().unwrap()))
92+
}
93+
8994
#[inline]
9095
pub fn hash_float(value: f64) -> Option<PyHash> {
9196
// cpython _Py_HashDouble

extra_tests/snippets/builtin_object.py

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
class MyObject:
22
pass
33

4+
45
assert not MyObject() == MyObject()
56
assert MyObject() != MyObject()
67
myobj = MyObject()
@@ -24,3 +25,10 @@ class MyObject:
2425
assert not hasattr(obj, 'a')
2526
obj.__dict__ = {'a': 1}
2627
assert obj.a == 1
28+
29+
# Value inside the formatter goes through a different path of resolution.
30+
# Check that it still works all the same
31+
d = {
32+
0: "ab",
33+
}
34+
assert "ab ab" == "{k[0]} {vv}".format(k=d, vv=d[0])

vm/src/dict_inner.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::{
1717
object::{Traverse, TraverseFn},
1818
};
1919
use num_traits::ToPrimitive;
20+
use rustpython_common::hash::hash_integer;
2021
use std::{fmt, mem::size_of, ops::ControlFlow};
2122

2223
// HashIndex is intended to be same size with hash::PyHash
@@ -993,8 +994,8 @@ impl DictKey for usize {
993994
*self
994995
}
995996

996-
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
997-
Ok(vm.state.hash_secret.hash_value(self))
997+
fn key_hash(&self, _vm: &VirtualMachine) -> PyResult<HashValue> {
998+
Ok(hash_integer(*self))
998999
}
9991000

10001001
fn key_is(&self, _other: &PyObject) -> bool {

0 commit comments

Comments
 (0)