mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Add derive key generation for record hashing
This commit is contained in:
parent
fd421c005d
commit
ad4d98be9c
3 changed files with 97 additions and 10 deletions
|
@ -10,5 +10,7 @@ pub(crate) fn derive_hash(
|
|||
key: FlatHashKey,
|
||||
_def_symbol: Symbol,
|
||||
) -> DerivedBody {
|
||||
match key {}
|
||||
match key {
|
||||
FlatHashKey::Record(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_module::{ident::Lowercase, symbol::Symbol};
|
||||
use roc_types::subs::{Content, FlatType, Subs, Variable};
|
||||
|
||||
use crate::DeriveError;
|
||||
use crate::{
|
||||
util::{check_derivable_ext_var, debug_name_record},
|
||||
DeriveError,
|
||||
};
|
||||
|
||||
#[derive(Hash)]
|
||||
pub enum FlatHash {
|
||||
|
@ -12,11 +15,16 @@ pub enum FlatHash {
|
|||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
|
||||
pub enum FlatHashKey {}
|
||||
pub enum FlatHashKey {
|
||||
// Unfortunate that we must allocate here, c'est la vie
|
||||
Record(Vec<Lowercase>),
|
||||
}
|
||||
|
||||
impl FlatHashKey {
|
||||
pub(crate) fn debug_name(&self) -> String {
|
||||
unreachable!() // yet
|
||||
match self {
|
||||
FlatHashKey::Record(fields) => debug_name_record(fields),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,8 +39,26 @@ impl FlatHash {
|
|||
Symbol::STR_STR => Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_STR_BYTES)),
|
||||
_ => Err(Underivable),
|
||||
},
|
||||
FlatType::Record(_fields, _ext) => {
|
||||
Err(Underivable) // yet
|
||||
FlatType::Record(fields, ext) => {
|
||||
let (fields_iter, ext) = fields.unsorted_iterator_and_ext(subs, ext);
|
||||
|
||||
check_derivable_ext_var(subs, ext, |ext| {
|
||||
matches!(ext, Content::Structure(FlatType::EmptyRecord))
|
||||
})?;
|
||||
|
||||
let mut field_names = Vec::with_capacity(fields.len());
|
||||
for (field_name, record_field) in fields_iter {
|
||||
if record_field.is_optional() {
|
||||
// Can't derive a concrete decoder for optional fields, since those are
|
||||
// compile-time-polymorphic
|
||||
return Err(Underivable);
|
||||
}
|
||||
field_names.push(field_name.clone());
|
||||
}
|
||||
|
||||
field_names.sort();
|
||||
|
||||
Ok(Key(FlatHashKey::Record(field_names)))
|
||||
}
|
||||
FlatType::TagUnion(_tags, _ext) | FlatType::RecursiveTagUnion(_, _tags, _ext) => {
|
||||
Err(Underivable) // yet
|
||||
|
@ -40,7 +66,7 @@ impl FlatHash {
|
|||
FlatType::FunctionOrTagUnion(_name_index, _, _) => {
|
||||
Err(Underivable) // yet
|
||||
}
|
||||
FlatType::EmptyRecord => Err(Underivable), // yet
|
||||
FlatType::EmptyRecord => Ok(Key(FlatHashKey::Record(vec![]))),
|
||||
FlatType::EmptyTagUnion => {
|
||||
Err(Underivable) // yet
|
||||
}
|
||||
|
|
|
@ -4,11 +4,38 @@
|
|||
// For the `v!` macro we use uppercase variables when constructing tag unions.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::{util::check_single_lset_immediate, v};
|
||||
use crate::{
|
||||
test_key_eq, test_key_neq,
|
||||
util::{check_derivable, check_single_lset_immediate, check_underivable},
|
||||
v,
|
||||
};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_types::subs::Variable;
|
||||
|
||||
use roc_derive_key::DeriveBuiltin::Hash;
|
||||
use roc_derive_key::{hash::FlatHashKey, DeriveBuiltin::Hash, DeriveError, DeriveKey};
|
||||
|
||||
test_key_eq! {
|
||||
Hash,
|
||||
|
||||
same_record:
|
||||
v!({ a: v!(U8), }), v!({ a: v!(U8), })
|
||||
same_record_fields_diff_types:
|
||||
v!({ a: v!(U8), }), v!({ a: v!(STR), })
|
||||
same_record_fields_any_order:
|
||||
v!({ a: v!(U8), b: v!(U8), c: v!(U8), }),
|
||||
v!({ c: v!(U8), a: v!(U8), b: v!(U8), })
|
||||
explicit_empty_record_and_implicit_empty_record:
|
||||
v!(EMPTY_RECORD), v!({})
|
||||
}
|
||||
|
||||
test_key_neq! {
|
||||
Hash,
|
||||
|
||||
different_record_fields:
|
||||
v!({ a: v!(U8), }), v!({ b: v!(U8), })
|
||||
record_empty_vs_nonempty:
|
||||
v!(EMPTY_RECORD), v!({ a: v!(U8), })
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn immediates() {
|
||||
|
@ -26,3 +53,35 @@ fn immediates() {
|
|||
check_single_lset_immediate(Hash, v!(Symbol::LIST_LIST v!(U8)), Symbol::HASH_HASH_LIST);
|
||||
check_single_lset_immediate(Hash, v!(Symbol::LIST_LIST v!(STR)), Symbol::HASH_HASH_LIST);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optional_record_field_derive_error() {
|
||||
check_underivable(Hash, v!({ ?a: v!(U8), }), DeriveError::Underivable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derivable_record_ext_flex_var() {
|
||||
check_derivable(
|
||||
Hash,
|
||||
v!({ a: v!(STR), }* ),
|
||||
DeriveKey::Hash(FlatHashKey::Record(vec!["a".into()])),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derivable_record_ext_flex_able_var() {
|
||||
check_derivable(
|
||||
Hash,
|
||||
v!({ a: v!(STR), }a has Symbol::DECODE_DECODER ),
|
||||
DeriveKey::Hash(FlatHashKey::Record(vec!["a".into()])),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derivable_record_with_record_ext() {
|
||||
check_derivable(
|
||||
Hash,
|
||||
v!({ b: v!(STR), }{ a: v!(STR), } ),
|
||||
DeriveKey::Hash(FlatHashKey::Record(vec!["a".into(), "b".into()])),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue