mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
Merge pull request #4074 from roc-lang/dict-umentation
document why Dict is the way it is
This commit is contained in:
commit
74552f0bac
1 changed files with 30 additions and 6 deletions
|
@ -5,6 +5,16 @@ use core::{
|
|||
mem::{align_of, ManuallyDrop},
|
||||
};
|
||||
|
||||
/// At the moment, Roc's Dict is just an association list. Its lookups are O(n) but
|
||||
/// we haven't grown such big programs that it's a problem yet!
|
||||
///
|
||||
/// We do some things in this data structure that only make sense because the
|
||||
/// memory is managed in Roc:
|
||||
///
|
||||
/// 1. We don't implement an [`IntoIterator`] that iterates over owned values,
|
||||
/// since Roc owns the memory, not rust.
|
||||
/// 2. We use a union for [`RocDictItem`] instead of just a struct. See the
|
||||
/// comment on that data structure for why.
|
||||
#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct RocDict<K, V>(RocList<RocDictItem<K, V>>);
|
||||
|
@ -108,6 +118,26 @@ impl<K: Debug, V: Debug> Debug for RocDict<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Roc is constructing these values according to its memory layout rules.
|
||||
/// Specifically:
|
||||
///
|
||||
/// 1. fields with the highest alignment go first
|
||||
/// 2. then fields are sorted alphabetically
|
||||
///
|
||||
/// Taken together, these mean that if we have a value with higher alignment
|
||||
/// than the key, it'll be first in memory. Otherwise, the key will be first.
|
||||
/// Fortunately, the total amount of memory doesn't change, so we can use a
|
||||
/// union and disambiguate by examining the alignment of the key and value.
|
||||
///
|
||||
/// However, note that this only makes sense while we're storing KV pairs
|
||||
/// contiguously in memory. If we separate them at some point, we'll need to
|
||||
/// change this implementation drastically!
|
||||
#[derive(Eq)]
|
||||
union RocDictItem<K, V> {
|
||||
key_first: ManuallyDrop<KeyFirst<K, V>>,
|
||||
value_first: ManuallyDrop<ValueFirst<K, V>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(C)]
|
||||
struct KeyFirst<K, V> {
|
||||
|
@ -122,12 +152,6 @@ struct ValueFirst<K, V> {
|
|||
key: K,
|
||||
}
|
||||
|
||||
#[derive(Eq)]
|
||||
union RocDictItem<K, V> {
|
||||
key_first: ManuallyDrop<KeyFirst<K, V>>,
|
||||
value_first: ManuallyDrop<ValueFirst<K, V>>,
|
||||
}
|
||||
|
||||
impl<K, V> RocDictItem<K, V> {
|
||||
fn key(&self) -> &K {
|
||||
if align_of::<K>() >= align_of::<V>() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue