Avoid repeating empty TypeId's when calculating hash.

This commit is contained in:
Stephen Chung 2020-05-19 20:07:51 +08:00
parent 3295060dba
commit ab76a69b12
5 changed files with 81 additions and 80 deletions

View File

@ -12,7 +12,7 @@ use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
use crate::scope::{EntryType as ScopeEntryType, Scope}; use crate::scope::{EntryType as ScopeEntryType, Scope};
use crate::token::Position; use crate::token::Position;
use crate::utils::{StaticVec, EMPTY_TYPE_ID}; use crate::utils::StaticVec;
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
use crate::module::{resolvers, ModuleRef, ModuleResolver}; use crate::module::{resolvers, ModuleRef, ModuleResolver};
@ -25,7 +25,7 @@ use crate::stdlib::{
boxed::Box, boxed::Box,
collections::HashMap, collections::HashMap,
format, format,
iter::{empty, once, repeat}, iter::{empty, once},
mem, mem,
num::NonZeroUsize, num::NonZeroUsize,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
@ -215,8 +215,7 @@ impl<'a> State<'a> {
/// Since script-defined functions have `Dynamic` parameters, functions with the same name /// Since script-defined functions have `Dynamic` parameters, functions with the same name
/// and number of parameters are considered equivalent. /// and number of parameters are considered equivalent.
/// ///
/// The key of the `HashMap` is a `u64` hash calculated by the function `calc_fn_hash` /// The key of the `HashMap` is a `u64` hash calculated by the function `calc_fn_hash`.
/// with dummy parameter types `EMPTY_TYPE_ID()` repeated the correct number of times.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct FunctionsLib(HashMap<u64, SharedFnDef>); pub struct FunctionsLib(HashMap<u64, SharedFnDef>);
@ -226,9 +225,8 @@ impl FunctionsLib {
FunctionsLib( FunctionsLib(
vec.into_iter() vec.into_iter()
.map(|fn_def| { .map(|fn_def| {
// Qualifiers (none) + function name + placeholders (one for each parameter). // Qualifiers (none) + function name + number of arguments.
let args_iter = repeat(EMPTY_TYPE_ID()).take(fn_def.params.len()); let hash = calc_fn_hash(empty(), &fn_def.name, fn_def.params.len(), empty());
let hash = calc_fn_hash(empty(), &fn_def.name, args_iter);
(hash, fn_def.into()) (hash, fn_def.into())
}) })
.collect(), .collect(),
@ -253,8 +251,8 @@ impl FunctionsLib {
params: usize, params: usize,
public_only: bool, public_only: bool,
) -> Option<&FnDef> { ) -> Option<&FnDef> {
// Qualifiers (none) + function name + placeholders (one for each parameter). // Qualifiers (none) + function name + number of arguments.
let hash_fn_def = calc_fn_hash(empty(), name, repeat(EMPTY_TYPE_ID()).take(params)); let hash_fn_def = calc_fn_hash(empty(), name, params, empty());
let fn_def = self.get_function(hash_fn_def); let fn_def = self.get_function(hash_fn_def);
match fn_def.as_ref().map(|f| f.access) { match fn_def.as_ref().map(|f| f.access) {
@ -873,8 +871,13 @@ impl Engine {
pos: Position, pos: Position,
level: usize, level: usize,
) -> Result<(Dynamic, bool), Box<EvalAltResult>> { ) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
// Qualifiers (none) + function name + argument `TypeId`'s. // Qualifiers (none) + function name + number of arguments + argument `TypeId`'s.
let hash_fn = calc_fn_hash(empty(), fn_name, args.iter().map(|a| a.type_id())); let hash_fn = calc_fn_hash(
empty(),
fn_name,
args.len(),
args.iter().map(|a| a.type_id()),
);
let hashes = (hash_fn, hash_fn_def); let hashes = (hash_fn, hash_fn_def);
match fn_name { match fn_name {
@ -1322,7 +1325,7 @@ impl Engine {
Dynamic(Union::Array(mut rhs_value)) => { Dynamic(Union::Array(mut rhs_value)) => {
let op = "=="; let op = "==";
let def_value = false.into(); let def_value = false.into();
let hash_fn_def = calc_fn_hash(empty(), op, repeat(EMPTY_TYPE_ID()).take(2)); let hash_fn_def = calc_fn_hash(empty(), op, 2, empty());
// Call the `==` operator to compare each value // Call the `==` operator to compare each value
for value in rhs_value.iter_mut() { for value in rhs_value.iter_mut() {
@ -1331,7 +1334,8 @@ impl Engine {
let pos = rhs.position(); let pos = rhs.position();
// Qualifiers (none) + function name + argument `TypeId`'s. // Qualifiers (none) + function name + argument `TypeId`'s.
let hash_fn = calc_fn_hash(empty(), op, args.iter().map(|a| a.type_id())); let hash_fn =
calc_fn_hash(empty(), op, args.len(), args.iter().map(|a| a.type_id()));
let hashes = (hash_fn, hash_fn_def); let hashes = (hash_fn, hash_fn_def);
let (r, _) = self let (r, _) = self
@ -1486,7 +1490,7 @@ impl Engine {
let mut args: StaticVec<_> = arg_values.iter_mut().collect(); let mut args: StaticVec<_> = arg_values.iter_mut().collect();
if name == KEYWORD_EVAL && args.len() == 1 && args.get(0).is::<String>() { if name == KEYWORD_EVAL && args.len() == 1 && args.get(0).is::<String>() {
let hash_fn = calc_fn_hash(empty(), name, once(TypeId::of::<String>())); let hash_fn = calc_fn_hash(empty(), name, 1, once(TypeId::of::<String>()));
if !self.has_override(state, (hash_fn, *hash_fn_def)) { if !self.has_override(state, (hash_fn, *hash_fn_def)) {
// eval - only in function call style // eval - only in function call style
@ -1547,11 +1551,11 @@ impl Engine {
// Rust functions are indexed in two steps: // Rust functions are indexed in two steps:
// 1) Calculate a hash in a similar manner to script-defined functions, // 1) Calculate a hash in a similar manner to script-defined functions,
// i.e. qualifiers + function name + dummy parameter types (one for each parameter). // i.e. qualifiers + function name + number of arguments.
// 2) Calculate a second hash with no qualifiers, empty function name, and // 2) Calculate a second hash with no qualifiers, empty function name,
// the actual list of parameter `TypeId`'.s // zero number of arguments, and the actual list of argument `TypeId`'.s
let hash_fn_args = let hash_fn_args =
calc_fn_hash(empty(), "", args.iter().map(|a| a.type_id())); calc_fn_hash(empty(), "", 0, args.iter().map(|a| a.type_id()));
// 3) The final hash is the XOR of the two hashes. // 3) The final hash is the XOR of the two hashes.
let hash_fn_native = *hash_fn_def ^ hash_fn_args; let hash_fn_native = *hash_fn_def ^ hash_fn_args;

View File

@ -8,18 +8,22 @@ use crate::fn_native::{
CallableFunction::{Method, Pure}, CallableFunction::{Method, Pure},
FnCallArgs, IteratorFn, SharedFunction, FnCallArgs, IteratorFn, SharedFunction,
}; };
use crate::parser::{FnAccess, AST}; use crate::parser::{
FnAccess,
FnAccess::{Private, Public},
AST,
};
use crate::result::EvalAltResult; use crate::result::EvalAltResult;
use crate::scope::{Entry as ScopeEntry, EntryType as ScopeEntryType, Scope}; use crate::scope::{Entry as ScopeEntry, EntryType as ScopeEntryType, Scope};
use crate::token::{Position, Token}; use crate::token::{Position, Token};
use crate::utils::{StaticVec, EMPTY_TYPE_ID}; use crate::utils::StaticVec;
use crate::stdlib::{ use crate::stdlib::{
any::TypeId, any::TypeId,
boxed::Box, boxed::Box,
collections::HashMap, collections::HashMap,
fmt, fmt,
iter::{empty, repeat}, iter::empty,
mem, mem,
num::NonZeroUsize, num::NonZeroUsize,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
@ -30,9 +34,6 @@ use crate::stdlib::{
vec::Vec, vec::Vec,
}; };
/// Default function access mode.
const DEF_ACCESS: FnAccess = FnAccess::Public;
/// Return type of module-level Rust function. /// Return type of module-level Rust function.
pub type FuncReturn<T> = Result<T, Box<EvalAltResult>>; pub type FuncReturn<T> = Result<T, Box<EvalAltResult>>;
@ -281,7 +282,7 @@ impl Module {
params: &[TypeId], params: &[TypeId],
func: CallableFunction, func: CallableFunction,
) -> u64 { ) -> u64 {
let hash_fn = calc_fn_hash(empty(), &name, params.iter().cloned()); let hash_fn = calc_fn_hash(empty(), &name, params.len(), params.iter().cloned());
let params = params.into_iter().cloned().collect(); let params = params.into_iter().cloned().collect();
@ -312,7 +313,7 @@ impl Module {
) -> u64 { ) -> u64 {
let f = move |_: &mut FnCallArgs| func().map(Dynamic::from); let f = move |_: &mut FnCallArgs| func().map(Dynamic::from);
let arg_types = []; let arg_types = [];
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f))) self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
} }
/// Set a Rust function taking one parameter into the module, returning a hash key. /// Set a Rust function taking one parameter into the module, returning a hash key.
@ -337,7 +338,7 @@ impl Module {
let f = let f =
move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from); move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from);
let arg_types = [TypeId::of::<A>()]; let arg_types = [TypeId::of::<A>()];
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f))) self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
} }
/// Set a Rust function taking one mutable parameter into the module, returning a hash key. /// Set a Rust function taking one mutable parameter into the module, returning a hash key.
@ -363,7 +364,7 @@ impl Module {
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from) func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
}; };
let arg_types = [TypeId::of::<A>()]; let arg_types = [TypeId::of::<A>()];
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Method(Box::new(f))) self.set_fn(name.into(), Public, &arg_types, Method(Box::new(f)))
} }
/// Set a Rust function taking two parameters into the module, returning a hash key. /// Set a Rust function taking two parameters into the module, returning a hash key.
@ -394,7 +395,7 @@ impl Module {
func(a, b).map(Dynamic::from) func(a, b).map(Dynamic::from)
}; };
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()]; let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f))) self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
} }
/// Set a Rust function taking two parameters (the first one mutable) into the module, /// Set a Rust function taking two parameters (the first one mutable) into the module,
@ -429,7 +430,7 @@ impl Module {
func(a, b).map(Dynamic::from) func(a, b).map(Dynamic::from)
}; };
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()]; let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Method(Box::new(f))) self.set_fn(name.into(), Public, &arg_types, Method(Box::new(f)))
} }
/// Set a Rust function taking three parameters into the module, returning a hash key. /// Set a Rust function taking three parameters into the module, returning a hash key.
@ -467,7 +468,7 @@ impl Module {
func(a, b, c).map(Dynamic::from) func(a, b, c).map(Dynamic::from)
}; };
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]; let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Pure(Box::new(f))) self.set_fn(name.into(), Public, &arg_types, Pure(Box::new(f)))
} }
/// Set a Rust function taking three parameters (the first one mutable) into the module, /// Set a Rust function taking three parameters (the first one mutable) into the module,
@ -506,7 +507,7 @@ impl Module {
func(a, b, c).map(Dynamic::from) func(a, b, c).map(Dynamic::from)
}; };
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()]; let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
self.set_fn(name.into(), DEF_ACCESS, &arg_types, Method(Box::new(f))) self.set_fn(name.into(), Public, &arg_types, Method(Box::new(f)))
} }
/// Get a Rust function. /// Get a Rust function.
@ -617,27 +618,24 @@ impl Module {
// Index all variables // Index all variables
for (var_name, value) in &module.variables { for (var_name, value) in &module.variables {
// Qualifiers + variable name // Qualifiers + variable name
let hash_var = calc_fn_hash(qualifiers.iter().map(|&v| v), var_name, empty()); let hash_var = calc_fn_hash(qualifiers.iter().map(|&v| v), var_name, 0, empty());
variables.push((hash_var, value.clone())); variables.push((hash_var, value.clone()));
} }
// Index all Rust functions // Index all Rust functions
for (name, access, params, func) in module.functions.values() { for (name, access, params, func) in module.functions.values() {
match access { match access {
// Private functions are not exported // Private functions are not exported
FnAccess::Private => continue, Private => continue,
FnAccess::Public => (), Public => (),
} }
// Rust functions are indexed in two steps: // Rust functions are indexed in two steps:
// 1) Calculate a hash in a similar manner to script-defined functions, // 1) Calculate a hash in a similar manner to script-defined functions,
// i.e. qualifiers + function name + dummy parameter types (one for each parameter). // i.e. qualifiers + function name + number of arguments.
let hash_fn_def = calc_fn_hash( let hash_fn_def =
qualifiers.iter().map(|&v| v), calc_fn_hash(qualifiers.iter().map(|&v| v), name, params.len(), empty());
name, // 2) Calculate a second hash with no qualifiers, empty function name,
repeat(EMPTY_TYPE_ID()).take(params.len()), // zero number of arguments, and the actual list of argument `TypeId`'.s
); let hash_fn_args = calc_fn_hash(empty(), "", 0, params.iter().cloned());
// 2) Calculate a second hash with no qualifiers, empty function name, and
// the actual list of parameter `TypeId`'.s
let hash_fn_args = calc_fn_hash(empty(), "", params.iter().cloned());
// 3) The final hash is the XOR of the two hashes. // 3) The final hash is the XOR of the two hashes.
let hash_fn_native = hash_fn_def ^ hash_fn_args; let hash_fn_native = hash_fn_def ^ hash_fn_args;
@ -647,14 +645,15 @@ impl Module {
for fn_def in module.fn_lib.values() { for fn_def in module.fn_lib.values() {
match fn_def.access { match fn_def.access {
// Private functions are not exported // Private functions are not exported
FnAccess::Private => continue, Private => continue,
DEF_ACCESS => (), Public => (),
} }
// Qualifiers + function name + placeholders (one for each parameter) // Qualifiers + function name + number of arguments.
let hash_fn_def = calc_fn_hash( let hash_fn_def = calc_fn_hash(
qualifiers.iter().map(|&v| v), qualifiers.iter().map(|&v| v),
&fn_def.name, &fn_def.name,
repeat(EMPTY_TYPE_ID()).take(fn_def.params.len()), fn_def.params.len(),
empty(),
); );
functions.push((hash_fn_def, CallableFunction::Script(fn_def.clone()).into())); functions.push((hash_fn_def, CallableFunction::Script(fn_def.clone()).into()));
} }

View File

@ -119,7 +119,12 @@ fn call_fn(
pos: Position, pos: Position,
) -> Result<Option<Dynamic>, Box<EvalAltResult>> { ) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
// Search built-in's and external functions // Search built-in's and external functions
let hash_fn = calc_fn_hash(empty(), fn_name, args.iter().map(|a| a.type_id())); let hash_fn = calc_fn_hash(
empty(),
fn_name,
args.len(),
args.iter().map(|a| a.type_id()),
);
global_module global_module
.get_fn(hash_fn) .get_fn(hash_fn)

View File

@ -7,7 +7,7 @@ use crate::error::{LexError, ParseError, ParseErrorType};
use crate::optimize::{optimize_into_ast, OptimizationLevel}; use crate::optimize::{optimize_into_ast, OptimizationLevel};
use crate::scope::{EntryType as ScopeEntryType, Scope}; use crate::scope::{EntryType as ScopeEntryType, Scope};
use crate::token::{Position, Token, TokenIterator}; use crate::token::{Position, Token, TokenIterator};
use crate::utils::{StaticVec, EMPTY_TYPE_ID}; use crate::utils::StaticVec;
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
use crate::module::ModuleRef; use crate::module::ModuleRef;
@ -22,7 +22,7 @@ use crate::stdlib::{
char, char,
collections::HashMap, collections::HashMap,
format, format,
iter::{empty, repeat, Peekable}, iter::{empty, Peekable},
num::NonZeroUsize, num::NonZeroUsize,
ops::{Add, Deref, DerefMut}, ops::{Add, Deref, DerefMut},
rc::Rc, rc::Rc,
@ -767,13 +767,14 @@ fn parse_call_expr<'a>(
// Rust functions are indexed in two steps: // Rust functions are indexed in two steps:
// 1) Calculate a hash in a similar manner to script-defined functions, // 1) Calculate a hash in a similar manner to script-defined functions,
// i.e. qualifiers + function name + no parameters. // i.e. qualifiers + function name + number of arguments.
// 2) Calculate a second hash with no qualifiers, empty function name, and // 2) Calculate a second hash with no qualifiers, empty function name,
// the actual list of parameter `TypeId`'.s // zero number of arguments, and the actual list of argument `TypeId`'s.
// 3) The final hash is the XOR of the two hashes. // 3) The final hash is the XOR of the two hashes.
calc_fn_hash(modules.iter().map(|(m, _)| m.as_str()), &id, empty()) let qualifiers = modules.iter().map(|(m, _)| m.as_str());
calc_fn_hash(qualifiers, &id, 0, empty())
} else { } else {
calc_fn_hash(empty(), &id, empty()) calc_fn_hash(empty(), &id, 0, empty())
} }
}; };
// Qualifiers (none) + function name + no parameters. // Qualifiers (none) + function name + no parameters.
@ -799,7 +800,6 @@ fn parse_call_expr<'a>(
// id(...args) // id(...args)
(Token::RightParen, _) => { (Token::RightParen, _) => {
eat_token(input, Token::RightParen); eat_token(input, Token::RightParen);
let args_iter = repeat(EMPTY_TYPE_ID()).take(args.len());
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
let hash_fn_def = { let hash_fn_def = {
@ -808,13 +808,14 @@ fn parse_call_expr<'a>(
// Rust functions are indexed in two steps: // Rust functions are indexed in two steps:
// 1) Calculate a hash in a similar manner to script-defined functions, // 1) Calculate a hash in a similar manner to script-defined functions,
// i.e. qualifiers + function name + dummy parameter types (one for each parameter). // i.e. qualifiers + function name + number of arguments.
// 2) Calculate a second hash with no qualifiers, empty function name, and // 2) Calculate a second hash with no qualifiers, empty function name,
// the actual list of parameter `TypeId`'.s // zero number of arguments, and the actual list of argument `TypeId`'s.
// 3) The final hash is the XOR of the two hashes. // 3) The final hash is the XOR of the two hashes.
calc_fn_hash(modules.iter().map(|(m, _)| m.as_str()), &id, args_iter) let qualifiers = modules.iter().map(|(m, _)| m.as_str());
calc_fn_hash(qualifiers, &id, args.len(), empty())
} else { } else {
calc_fn_hash(empty(), &id, args_iter) calc_fn_hash(empty(), &id, args.len(), empty())
} }
}; };
// Qualifiers (none) + function name + dummy parameter types (one for each parameter). // Qualifiers (none) + function name + dummy parameter types (one for each parameter).
@ -1297,7 +1298,7 @@ fn parse_primary<'a>(
let modules = modules.as_mut().unwrap(); let modules = modules.as_mut().unwrap();
// Qualifiers + variable name // Qualifiers + variable name
*hash = calc_fn_hash(modules.iter().map(|(v, _)| v.as_str()), name, empty()); *hash = calc_fn_hash(modules.iter().map(|(v, _)| v.as_str()), name, 0, empty());
modules.set_index(state.find_module(&modules.get(0).0)); modules.set_index(state.find_module(&modules.get(0).0));
} }
_ => (), _ => (),
@ -1362,7 +1363,7 @@ fn parse_unary<'a>(
// Call negative function // Call negative function
expr => { expr => {
let op = "-"; let op = "-";
let hash = calc_fn_hash(empty(), op, repeat(EMPTY_TYPE_ID()).take(2)); let hash = calc_fn_hash(empty(), op, 2, empty());
let mut args = StaticVec::new(); let mut args = StaticVec::new();
args.push(expr); args.push(expr);
@ -1388,7 +1389,7 @@ fn parse_unary<'a>(
args.push(parse_primary(input, state, level + 1, allow_stmt_expr)?); args.push(parse_primary(input, state, level + 1, allow_stmt_expr)?);
let op = "!"; let op = "!";
let hash = calc_fn_hash(empty(), op, repeat(EMPTY_TYPE_ID()).take(2)); let hash = calc_fn_hash(empty(), op, 2, empty());
Ok(Expr::FnCall(Box::new(( Ok(Expr::FnCall(Box::new((
(op.into(), pos), (op.into(), pos),
@ -1492,7 +1493,7 @@ fn parse_op_assignment_stmt<'a>(
args.push(lhs_copy); args.push(lhs_copy);
args.push(rhs); args.push(rhs);
let hash = calc_fn_hash(empty(), &op, repeat(EMPTY_TYPE_ID()).take(args.len())); let hash = calc_fn_hash(empty(), &op, args.len(), empty());
let rhs_expr = Expr::FnCall(Box::new(((op, pos), None, hash, args, None))); let rhs_expr = Expr::FnCall(Box::new(((op, pos), None, hash, args, None)));
make_assignment_stmt(state, lhs, rhs_expr, pos) make_assignment_stmt(state, lhs, rhs_expr, pos)
@ -1780,7 +1781,7 @@ fn parse_binary_op<'a>(
let cmp_def = Some(false.into()); let cmp_def = Some(false.into());
let op = op_token.syntax(); let op = op_token.syntax();
let hash = calc_fn_hash(empty(), &op, repeat(EMPTY_TYPE_ID()).take(2)); let hash = calc_fn_hash(empty(), &op, 2, empty());
let mut args = StaticVec::new(); let mut args = StaticVec::new();
args.push(root); args.push(root);
@ -1839,8 +1840,7 @@ fn parse_binary_op<'a>(
Expr::FnCall(x) => { Expr::FnCall(x) => {
let ((id, _), _, hash, args, _) = x.as_mut(); let ((id, _), _, hash, args, _) = x.as_mut();
// Recalculate function call hash because there is an additional argument // Recalculate function call hash because there is an additional argument
let args_iter = repeat(EMPTY_TYPE_ID()).take(args.len() + 1); *hash = calc_fn_hash(empty(), id, args.len() + 1, empty());
*hash = calc_fn_hash(empty(), id, args_iter);
} }
_ => (), _ => (),
} }
@ -2540,12 +2540,8 @@ fn parse_global_level<'a>(
let mut state = ParseState::new(max_expr_depth.1); let mut state = ParseState::new(max_expr_depth.1);
let func = parse_fn(input, &mut state, access, 0, true)?; let func = parse_fn(input, &mut state, access, 0, true)?;
// Qualifiers (none) + function name + argument `TypeId`'s // Qualifiers (none) + function name + number of arguments.
let hash = calc_fn_hash( let hash = calc_fn_hash(empty(), &func.name, func.params.len(), empty());
empty(),
&func.name,
repeat(EMPTY_TYPE_ID()).take(func.params.len()),
);
functions.insert(hash, func); functions.insert(hash, func);
continue; continue;

View File

@ -21,11 +21,6 @@ use crate::stdlib::collections::hash_map::DefaultHasher;
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use ahash::AHasher; use ahash::AHasher;
#[inline(always)]
pub fn EMPTY_TYPE_ID() -> TypeId {
TypeId::of::<()>()
}
/// Calculate a `u64` hash key from a module-qualified function name and parameter types. /// Calculate a `u64` hash key from a module-qualified function name and parameter types.
/// ///
/// Module names are passed in via `&str` references from an iterator. /// Module names are passed in via `&str` references from an iterator.
@ -37,6 +32,7 @@ pub fn EMPTY_TYPE_ID() -> TypeId {
pub fn calc_fn_spec<'a>( pub fn calc_fn_spec<'a>(
modules: impl Iterator<Item = &'a str>, modules: impl Iterator<Item = &'a str>,
fn_name: &str, fn_name: &str,
num: usize,
params: impl Iterator<Item = TypeId>, params: impl Iterator<Item = TypeId>,
) -> u64 { ) -> u64 {
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
@ -47,6 +43,7 @@ pub fn calc_fn_spec<'a>(
// We always skip the first module // We always skip the first module
modules.skip(1).for_each(|m| m.hash(&mut s)); modules.skip(1).for_each(|m| m.hash(&mut s));
s.write(fn_name.as_bytes()); s.write(fn_name.as_bytes());
s.write_usize(num);
params.for_each(|t| t.hash(&mut s)); params.for_each(|t| t.hash(&mut s));
s.finish() s.finish()
} }