diff --git a/src/array/dictionary/mod.rs b/src/array/dictionary/mod.rs index a4be1ea210..3a23e670a1 100644 --- a/src/array/dictionary/mod.rs +++ b/src/array/dictionary/mod.rs @@ -1,3 +1,4 @@ +use std::hash::Hash; use std::hint::unreachable_unchecked; use crate::{ @@ -34,7 +35,7 @@ use super::{new_null_array, specification::check_indexes}; /// /// Any implementation of this trait must ensure that `always_fits_usize` only /// returns `true` if all values succeeds on `value::try_into::().unwrap()`. -pub unsafe trait DictionaryKey: NativeType + TryInto + TryFrom { +pub unsafe trait DictionaryKey: NativeType + TryInto + TryFrom + Hash { /// The corresponding [`IntegerType`] of this key const KEY_TYPE: IntegerType; diff --git a/src/array/dictionary/value_map.rs b/src/array/dictionary/value_map.rs index e1f65b2b5a..5c85f8085c 100644 --- a/src/array/dictionary/value_map.rs +++ b/src/array/dictionary/value_map.rs @@ -17,7 +17,7 @@ use super::DictionaryKey; pub struct ValueMap { values: M, - map: HashMap, // NB: *only* use insert_hashed_nocheck() and no other hashmap API + map: HashMap, // NB: *only* use insert_hashed_nocheck() and no other hashmap API } impl ValueMap { @@ -53,7 +53,7 @@ impl ValueMap { )) } RawEntryMut::Vacant(entry) => { - entry.insert_hashed_nocheck(hash, index, key); // NB: don't use .insert() here! + entry.insert_hashed_nocheck(hash, key, ()); // NB: don't use .insert() here! } } } @@ -95,16 +95,18 @@ impl ValueMap { let hash = hasher.finish(); Ok( - match self.map.raw_entry_mut().from_hash(hash, |index| { + match self.map.raw_entry_mut().from_hash(hash, |key| { + // safety: we've already checked (the inverse) when we pushed it, so it should be ok? + let index = unsafe { key.as_usize() }; // safety: invariant of the struct, it's always in bounds since we maintain it - let stored_value = unsafe { self.values.value_unchecked_at(*index) }; + let stored_value = unsafe { self.values.value_unchecked_at(index) }; stored_value.borrow() == value.as_indexed() }) { - RawEntryMut::Occupied(entry) => *entry.get(), + RawEntryMut::Occupied(entry) => *entry.key(), RawEntryMut::Vacant(entry) => { let index = self.values.len(); let key = K::try_from(index).map_err(|_| Error::Overflow)?; - entry.insert_hashed_nocheck(hash, index, key); // NB: don't use .insert() here! + entry.insert_hashed_nocheck(hash, key, ()); // NB: don't use .insert() here! push(&mut self.values, value)?; key }