mirror of
https://github.com/roc-lang/roc.git
synced 2025-11-03 22:13:35 +00:00
Choose hash implementation for ranged number based on default width
Closes #4416
This commit is contained in:
parent
3305041316
commit
9c8a4ec027
3 changed files with 94 additions and 33 deletions
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue