mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Avoid allocating a vector of elements when hashing frozenset (#5408)
Adds a `try_fold_keys` method to Dict which allows performing common operations on all elements without needing to create a Vec first.
This commit is contained in:
@@ -436,12 +436,12 @@ impl PySetInner {
|
||||
((h ^ 89869747) ^ (h.wrapping_shl(16))).wrapping_mul(3644798167)
|
||||
}
|
||||
// Factor in the number of active entries
|
||||
let mut hash: u64 = (self.elements().len() as u64 + 1).wrapping_mul(1927868237);
|
||||
let mut hash: u64 = (self.len() as u64 + 1).wrapping_mul(1927868237);
|
||||
// Xor-in shuffled bits from every entry's hash field because xor is
|
||||
// commutative and a frozenset hash should be independent of order.
|
||||
for element in self.elements().iter() {
|
||||
hash ^= _shuffle_bits(element.hash(vm)? as u64);
|
||||
}
|
||||
hash = self.content.try_fold_keys(hash, |h, element| {
|
||||
Ok(h ^ _shuffle_bits(element.hash(vm)? as u64))
|
||||
})?;
|
||||
// Disperse patterns arising in nested frozensets
|
||||
hash ^= (hash >> 11) ^ (hash >> 25);
|
||||
hash = hash.wrapping_mul(69069).wrapping_add(907133923);
|
||||
|
||||
@@ -530,6 +530,17 @@ impl<T: Clone> Dict<T> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn try_fold_keys<Acc, Fold>(&self, init: Acc, f: Fold) -> PyResult<Acc>
|
||||
where
|
||||
Fold: FnMut(Acc, &PyObject) -> PyResult<Acc>,
|
||||
{
|
||||
self.read()
|
||||
.entries
|
||||
.iter()
|
||||
.filter_map(|v| v.as_ref().map(|v| v.key.as_object()))
|
||||
.try_fold(init, f)
|
||||
}
|
||||
|
||||
/// Lookup the index for the given key.
|
||||
#[cfg_attr(feature = "flame-it", flame("Dict"))]
|
||||
fn lookup<K: DictKey + ?Sized>(
|
||||
|
||||
Reference in New Issue
Block a user