Choose hash implementation for ranged number based on default width

Closes #4416
This commit is contained in:
Ayaz Hafiz 2022-11-16 13:57:03 -06:00
parent 3305041316
commit 9c8a4ec027
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 94 additions and 33 deletions

View file

@ -105,42 +105,29 @@ impl FlatHash {
//
FlatType::Func(..) => Err(Underivable),
},
Content::Alias(sym, _, real_var, _) => match sym {
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_U8))
}
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_U16))
}
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_U32))
}
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_U64))
}
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_ADD_U128))
}
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I8))
}
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I16))
}
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I32))
}
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I64))
}
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => {
Ok(SingleLambdaSetImmediate(Symbol::HASH_HASH_I128))
}
Content::Alias(sym, _, real_var, _) => match num_symbol_to_hash_lambda(sym) {
Some(lambda) => Ok(lambda),
// NB: I believe it is okay to unwrap opaques here because derivers are only used
// by the backend, and the backend treats opaques like structural aliases.
_ => Self::from_var(subs, real_var),
None => Self::from_var(subs, real_var),
},
Content::RangedNumber(_) => Err(Underivable),
Content::RangedNumber(range) => {
// Find the integer we're going to compile to, that'll tell us what lambda we
// should resolve to.
//
// Note that at this point, we don't need to update the underlying type variable.
// That's because
//
// - If the type variable always had a ground constructor after solving, we would
// have already refined the ranged number during obligation checking.
//
// - If the type variable was generalized, then this branch is only reached
// during monomorphization, at which point we always choose a default layout
// for ranged numbers, without concern for reification to a ground type.
let chosen_width = range.default_compilation_width();
let lambda = num_symbol_to_hash_lambda(chosen_width.symbol()).unwrap();
Ok(lambda)
}
//
Content::RecursionVar { structure, .. } => Self::from_var(subs, structure),
//
@ -153,3 +140,40 @@ impl FlatHash {
}
}
}
const fn num_symbol_to_hash_lambda(symbol: Symbol) -> Option<FlatHash> {
use FlatHash::*;
match symbol {
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_ADD_U8))
}
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_ADD_U16))
}
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_ADD_U32))
}
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_ADD_U64))
}
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_ADD_U128))
}
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_HASH_I8))
}
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_HASH_I16))
}
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_HASH_I32))
}
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_HASH_I64))
}
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => {
Some(SingleLambdaSetImmediate(Symbol::HASH_HASH_I128))
}
_ => None,
}
}

View file

@ -8220,4 +8220,20 @@ mod solve_expr {
"{} -> Task",
)
}
#[test]
fn choose_ranged_num_for_hash() {
infer_queries!(
indoc!(
r#"
app "test" provides [main] to "./platform"
main =
\h -> Hash.hash h 7
# ^^^^^^^^^
"#
),
@"Hash#Hash.hash(1) : a, I64 -[[Hash.hashI64(12)]]-> a | a has Hasher"
)
}
}

View file

@ -1,3 +1,5 @@
use roc_module::symbol::Symbol;
use crate::subs::Variable;
/// A bound placed on a number because of its literal value.
@ -304,6 +306,25 @@ impl IntLitWidth {
}
}
}
pub const fn symbol(&self) -> Symbol {
match self {
IntLitWidth::U8 => Symbol::NUM_U8,
IntLitWidth::U16 => Symbol::NUM_U16,
IntLitWidth::U32 => Symbol::NUM_U32,
IntLitWidth::U64 => Symbol::NUM_U64,
IntLitWidth::U128 => Symbol::NUM_U128,
IntLitWidth::I8 => Symbol::NUM_I8,
IntLitWidth::I16 => Symbol::NUM_I16,
IntLitWidth::I32 => Symbol::NUM_I32,
IntLitWidth::I64 => Symbol::NUM_I64,
IntLitWidth::I128 => Symbol::NUM_I128,
IntLitWidth::Nat => Symbol::NUM_NAT,
IntLitWidth::F32 => Symbol::NUM_F32,
IntLitWidth::F64 => Symbol::NUM_F64,
IntLitWidth::Dec => Symbol::NUM_DEC,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]