diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 0cc628f4..3b07ecfd 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -666,7 +666,7 @@ impl Expr { #[cfg(not(feature = "no_module"))] namespace: super::Namespace::NONE, name: KEYWORD_FN_PTR.into(), - hashes: calc_fn_hash(f.fn_name(), 1).into(), + hashes: calc_fn_hash(None, f.fn_name(), 1).into(), args: once(Self::StringConstant(f.fn_name().into(), pos)).collect(), capture_parent_scope: false, is_native_operator: false, diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index a9d3b096..68b63ecd 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -74,8 +74,8 @@ impl OpAssignment { .expect("op-assignment operator") .literal_syntax(); Self { - hash_op_assign: calc_fn_hash(op.literal_syntax(), 2), - hash_op: calc_fn_hash(op_raw, 2), + hash_op_assign: calc_fn_hash(None, op.literal_syntax(), 2), + hash_op: calc_fn_hash(None, op_raw, 2), op_assign: op.literal_syntax(), op: op_raw, pos, diff --git a/src/eval/global_state.rs b/src/eval/global_state.rs index 83b2b076..775fdda0 100644 --- a/src/eval/global_state.rs +++ b/src/eval/global_state.rs @@ -285,8 +285,8 @@ impl GlobalRuntimeState<'_> { #[must_use] pub(crate) fn hash_idx_get(&mut self) -> u64 { if self.fn_hash_indexing == (0, 0) { - let n1 = crate::calc_fn_hash(crate::engine::FN_IDX_GET, 2); - let n2 = crate::calc_fn_hash(crate::engine::FN_IDX_SET, 3); + let n1 = crate::calc_fn_hash(None, crate::engine::FN_IDX_GET, 2); + let n2 = crate::calc_fn_hash(None, crate::engine::FN_IDX_SET, 3); self.fn_hash_indexing = (n1, n2); n1 } else { @@ -298,8 +298,8 @@ impl GlobalRuntimeState<'_> { #[must_use] pub(crate) fn hash_idx_set(&mut self) -> u64 { if self.fn_hash_indexing == (0, 0) { - let n1 = crate::calc_fn_hash(crate::engine::FN_IDX_GET, 2); - let n2 = crate::calc_fn_hash(crate::engine::FN_IDX_SET, 3); + let n1 = crate::calc_fn_hash(None, crate::engine::FN_IDX_GET, 2); + let n2 = crate::calc_fn_hash(None, crate::engine::FN_IDX_SET, 3); self.fn_hash_indexing = (n1, n2); n2 } else { diff --git a/src/func/call.rs b/src/func/call.rs index 9445e714..a09bd70d 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -198,10 +198,8 @@ impl Engine { } let mut hash = args.as_ref().map_or(hash_base, |args| { - combine_hashes( - hash_base, - calc_fn_params_hash(args.iter().map(|a| a.type_id())), - ) + let hash_params = calc_fn_params_hash(args.iter().map(|a| a.type_id())); + combine_hashes(hash_base, hash_params) }); let cache = caches.fn_resolution_cache_mut(); @@ -611,7 +609,7 @@ impl Engine { if num_params < 0 || num_params > crate::MAX_USIZE_INT { false } else { - let hash_script = calc_fn_hash(fn_name.as_str(), num_params as usize); + let hash_script = calc_fn_hash(None, fn_name.as_str(), num_params as usize); self.has_script_fn(Some(global), caches, lib, hash_script) } .into(), @@ -815,7 +813,7 @@ impl Engine { let fn_name = fn_ptr.fn_name(); let args_len = call_args.len() + fn_ptr.curry().len(); // Recalculate hashes - let new_hash = calc_fn_hash(fn_name, args_len).into(); + let new_hash = calc_fn_hash(None, fn_name, args_len).into(); // Arguments are passed as-is, adding the curried arguments let mut curry = FnArgsVec::with_capacity(fn_ptr.curry().len()); curry.extend(fn_ptr.curry().iter().cloned()); @@ -857,8 +855,8 @@ impl Engine { // Recalculate hash let new_hash = FnCallHashes::from_all( #[cfg(not(feature = "no_function"))] - calc_fn_hash(fn_name, args_len), - calc_fn_hash(fn_name, args_len + 1), + calc_fn_hash(None, fn_name, args_len), + calc_fn_hash(None, fn_name, args_len + 1), ); // Replace the first argument with the object pointer, adding the curried arguments let mut curry = FnArgsVec::with_capacity(fn_ptr.curry().len()); @@ -944,8 +942,8 @@ impl Engine { // Recalculate the hash based on the new function name and new arguments hash = FnCallHashes::from_all( #[cfg(not(feature = "no_function"))] - calc_fn_hash(fn_name, call_args.len()), - calc_fn_hash(fn_name, call_args.len() + 1), + calc_fn_hash(None, fn_name, call_args.len()), + calc_fn_hash(None, fn_name, call_args.len() + 1), ); } } @@ -1036,9 +1034,9 @@ impl Engine { // Recalculate hash let args_len = total_args + curry.len(); hashes = if hashes.is_native_only() { - FnCallHashes::from_native(calc_fn_hash(name, args_len)) + FnCallHashes::from_native(calc_fn_hash(None, name, args_len)) } else { - calc_fn_hash(name, args_len).into() + calc_fn_hash(None, name, args_len).into() }; } // Handle Fn() @@ -1110,7 +1108,7 @@ impl Engine { return Ok(if num_params < 0 || num_params > crate::MAX_USIZE_INT { false } else { - let hash_script = calc_fn_hash(&fn_name, num_params as usize); + let hash_script = calc_fn_hash(None, &fn_name, num_params as usize); self.has_script_fn(Some(global), caches, lib, hash_script) } .into()); diff --git a/src/func/hashing.rs b/src/func/hashing.rs index a7ef71fb..bc29f67b 100644 --- a/src/func/hashing.rs +++ b/src/func/hashing.rs @@ -91,7 +91,7 @@ pub fn get_hasher() -> ahash::AHasher { /// The first module name is skipped. Hashing starts from the _second_ module in the chain. #[inline] #[must_use] -pub fn calc_qualified_var_hash<'a>( +pub fn calc_var_hash<'a>( modules: impl IntoIterator>, var_name: &str, ) -> u64 { @@ -113,9 +113,11 @@ pub fn calc_qualified_var_hash<'a>( /// Calculate a non-zero [`u64`] hash key from a namespace-qualified function name /// and the number of parameters, but no parameter types. /// -/// Module names are passed in via `&str` references from an iterator. +/// Module names making up the namespace are passed in via `&str` references from an iterator. /// Parameter types are passed in via [`TypeId`] values from an iterator. /// +/// If the function is not namespace-qualified, pass [`None`] as the namespace. +/// /// # Zeros /// /// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`. @@ -125,15 +127,15 @@ pub fn calc_qualified_var_hash<'a>( /// The first module name is skipped. Hashing starts from the _second_ module in the chain. #[inline] #[must_use] -pub fn calc_qualified_fn_hash<'a>( - modules: impl IntoIterator>, +pub fn calc_fn_hash<'a>( + namespace: impl IntoIterator>, fn_name: &str, num: usize, ) -> u64 { let s = &mut get_hasher(); // We always skip the first module - let iter = modules.into_iter(); + let iter = namespace.into_iter(); let len = iter.len(); iter.skip(1).for_each(|m| m.hash(s)); len.hash(s); @@ -146,20 +148,6 @@ pub fn calc_qualified_fn_hash<'a>( } } -/// Calculate a non-zero [`u64`] hash key from a non-namespace-qualified function name -/// and the number of parameters, but no parameter types. -/// -/// Parameter types are passed in via [`TypeId`] values from an iterator. -/// -/// # Zeros -/// -/// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`. -#[inline(always)] -#[must_use] -pub fn calc_fn_hash(fn_name: &str, num: usize) -> u64 { - calc_qualified_fn_hash(None, fn_name, num) -} - /// Calculate a non-zero [`u64`] hash key from a list of parameter types. /// /// Parameter types are passed in via [`TypeId`] values from an iterator. diff --git a/src/func/mod.rs b/src/func/mod.rs index d9b9db8c..8298a63e 100644 --- a/src/func/mod.rs +++ b/src/func/mod.rs @@ -20,8 +20,7 @@ pub use callable_function::CallableFunction; #[cfg(not(feature = "no_function"))] pub use func::Func; pub use hashing::{ - calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, calc_qualified_var_hash, - combine_hashes, get_hasher, StraightHashMap, + calc_fn_hash, calc_fn_params_hash, calc_var_hash, combine_hashes, get_hasher, StraightHashMap, }; pub use native::{ locked_read, locked_write, shared_get_mut, shared_make_mut, shared_take, shared_take_or_clone, diff --git a/src/func/native.rs b/src/func/native.rs index 851f52e7..f421c262 100644 --- a/src/func/native.rs +++ b/src/func/native.rs @@ -321,11 +321,11 @@ impl<'a> NativeCallContext<'a> { let hash = if is_method_call { FnCallHashes::from_all( #[cfg(not(feature = "no_function"))] - calc_fn_hash(fn_name, args_len - 1), - calc_fn_hash(fn_name, args_len), + calc_fn_hash(None, fn_name, args_len - 1), + calc_fn_hash(None, fn_name, args_len), ) } else { - calc_fn_hash(fn_name, args_len).into() + calc_fn_hash(None, fn_name, args_len).into() }; self.engine() diff --git a/src/lib.rs b/src/lib.rs index f09e2b66..bb26d72b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -237,10 +237,7 @@ pub use func::Shared; /// Alias to [`RefCell`][std::cell::RefCell] or [`RwLock`][std::sync::RwLock] depending on the `sync` feature flag. pub use func::Locked; -pub(crate) use func::{ - calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, calc_qualified_var_hash, - combine_hashes, -}; +pub(crate) use func::{calc_fn_hash, calc_fn_params_hash, calc_var_hash, combine_hashes}; pub use rhai_codegen::*; diff --git a/src/module/mod.rs b/src/module/mod.rs index e027f384..ccee905d 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -9,8 +9,8 @@ use crate::func::{ }; use crate::types::{dynamic::Variant, BloomFilterU64, CustomTypesCollection}; use crate::{ - calc_fn_hash, calc_fn_params_hash, calc_qualified_fn_hash, combine_hashes, Dynamic, Identifier, - ImmutableString, NativeCallContext, RhaiResultOf, Shared, SmartString, StaticVec, + calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Identifier, ImmutableString, + NativeCallContext, RhaiResultOf, Shared, SmartString, StaticVec, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -150,7 +150,7 @@ pub fn calc_native_fn_hash<'a>( fn_name: &str, params: &[TypeId], ) -> u64 { - let hash_script = calc_qualified_fn_hash(modules, fn_name, params.len()); + let hash_script = calc_fn_hash(modules, fn_name, params.len()); let hash_params = calc_fn_params_hash(params.iter().copied()); combine_hashes(hash_script, hash_params) } @@ -662,7 +662,7 @@ impl Module { let value = Dynamic::from(value); if self.indexed { - let hash_var = crate::calc_qualified_var_hash(Some(""), &ident); + let hash_var = crate::calc_var_hash(Some(""), &ident); self.all_variables .get_or_insert_with(|| Default::default()) .insert(hash_var, value.clone()); @@ -692,7 +692,7 @@ impl Module { // None + function name + number of arguments. let num_params = fn_def.params.len(); - let hash_script = crate::calc_fn_hash(&fn_def.name, num_params); + let hash_script = crate::calc_fn_hash(None, &fn_def.name, num_params); #[cfg(feature = "metadata")] let params_info = fn_def.params.iter().map(Into::into).collect(); self.functions.insert( @@ -1021,11 +1021,12 @@ impl Module { }; let name = name.as_ref(); - let hash_fn = calc_native_fn_hash(None, name, ¶m_types); + let hash_script = calc_fn_hash(None, name, param_types.len()); + let hash_params = calc_fn_params_hash(param_types.iter().copied()); + let hash_fn = combine_hashes(hash_script, hash_params); if is_dynamic { - self.dynamic_functions - .mark(calc_fn_hash(name, param_types.len())); + self.dynamic_functions.mark(hash_script); } self.functions.insert( @@ -2126,7 +2127,7 @@ impl Module { // Index all variables if let Some(ref v) = module.variables { for (var_name, value) in v { - let hash_var = crate::calc_qualified_var_hash(path.iter().copied(), var_name); + let hash_var = crate::calc_var_hash(path.iter().copied(), var_name); variables.insert(hash_var, value.clone()); } } @@ -2160,7 +2161,7 @@ impl Module { functions.insert(hash_qualified_fn, f.func.clone()); } else if cfg!(not(feature = "no_function")) { let hash_qualified_script = - crate::calc_qualified_fn_hash(path.iter().copied(), &f.name, f.num_params); + crate::calc_fn_hash(path.iter().copied(), &f.name, f.num_params); functions.insert(hash_qualified_script, f.func.clone()); } } diff --git a/src/optimizer.rs b/src/optimizer.rs index 0b7a13c2..86739689 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -151,7 +151,7 @@ impl<'a> OptimizerState<'a> { &mut self.caches, lib, fn_name, - calc_fn_hash(fn_name, arg_values.len()), + calc_fn_hash(None, fn_name, arg_values.len()), &mut arg_values.iter_mut().collect::>(), false, false, diff --git a/src/parser.rs b/src/parser.rs index 4d22d30b..20600e0b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -358,9 +358,9 @@ impl Expr { Self::Variable(x, .., pos) => { let ident = x.3.clone(); let getter = state.get_interned_getter(ident.as_str()); - let hash_get = calc_fn_hash(&getter, 1); + let hash_get = calc_fn_hash(None, &getter, 1); let setter = state.get_interned_setter(ident.as_str()); - let hash_set = calc_fn_hash(&setter, 2); + let hash_set = calc_fn_hash(None, &setter, 2); Self::Property( Box::new(((getter, hash_get), (setter, hash_set), ident)), @@ -576,7 +576,7 @@ impl Engine { #[cfg(not(feature = "no_module"))] let hash = if namespace.is_empty() { - calc_fn_hash(&id, 0) + calc_fn_hash(None, &id, 0) } else { let root = namespace.root(); let index = state.find_module(root); @@ -600,10 +600,10 @@ impl Engine { namespace.set_index(index); - crate::calc_qualified_fn_hash(namespace.iter().map(Ident::as_str), &id, 0) + crate::calc_fn_hash(namespace.iter().map(Ident::as_str), &id, 0) }; #[cfg(feature = "no_module")] - let hash = calc_fn_hash(&id, 0); + let hash = calc_fn_hash(None, &id, 0); let hashes = if is_valid_function_name(&id) { hash.into() @@ -645,7 +645,7 @@ impl Engine { #[cfg(not(feature = "no_module"))] let hash = if namespace.is_empty() { - calc_fn_hash(&id, args.len()) + calc_fn_hash(None, &id, args.len()) } else { let root = namespace.root(); let index = state.find_module(root); @@ -668,14 +668,10 @@ impl Engine { namespace.set_index(index); - crate::calc_qualified_fn_hash( - namespace.iter().map(Ident::as_str), - &id, - args.len(), - ) + crate::calc_fn_hash(namespace.iter().map(Ident::as_str), &id, args.len()) }; #[cfg(feature = "no_module")] - let hash = calc_fn_hash(&id, args.len()); + let hash = calc_fn_hash(None, &id, args.len()); let hashes = if is_valid_function_name(&id) { hash.into() @@ -1470,7 +1466,7 @@ impl Engine { }, )?; - let hash_script = calc_fn_hash(&func.name, func.params.len()); + let hash_script = calc_fn_hash(None, &func.name, func.params.len()); lib.insert(hash_script, func.into()); expr @@ -1835,7 +1831,7 @@ impl Engine { #[cfg(not(feature = "no_module"))] if let Some((.., namespace, hash, name)) = namespaced_variable { if !namespace.is_empty() { - *hash = crate::calc_qualified_var_hash(namespace.iter().map(Ident::as_str), name); + *hash = crate::calc_var_hash(namespace.iter().map(Ident::as_str), name); #[cfg(not(feature = "no_module"))] { @@ -1919,7 +1915,7 @@ impl Engine { Ok(FnCallExpr { name: state.get_interned_string("-"), - hashes: FnCallHashes::from_native(calc_fn_hash("-", 1)), + hashes: FnCallHashes::from_native(calc_fn_hash(None, "-", 1)), args, pos, is_native_operator: true, @@ -1947,7 +1943,7 @@ impl Engine { Ok(FnCallExpr { name: state.get_interned_string("+"), - hashes: FnCallHashes::from_native(calc_fn_hash("+", 1)), + hashes: FnCallHashes::from_native(calc_fn_hash(None, "+", 1)), args, pos, is_native_operator: true, @@ -1966,7 +1962,7 @@ impl Engine { Ok(FnCallExpr { name: state.get_interned_string("!"), - hashes: FnCallHashes::from_native(calc_fn_hash("!", 1)), + hashes: FnCallHashes::from_native(calc_fn_hash(None, "!", 1)), args, pos, is_native_operator: true, @@ -2187,8 +2183,8 @@ impl Engine { // Recalculate hash func.hashes = FnCallHashes::from_all( #[cfg(not(feature = "no_function"))] - calc_fn_hash(&func.name, func.args.len()), - calc_fn_hash(&func.name, func.args.len() + 1), + calc_fn_hash(None, &func.name, func.args.len()), + calc_fn_hash(None, &func.name, func.args.len() + 1), ); let rhs = Expr::MethodCall(func, func_pos); @@ -2233,8 +2229,8 @@ impl Engine { // Recalculate hash func.hashes = FnCallHashes::from_all( #[cfg(not(feature = "no_function"))] - calc_fn_hash(&func.name, func.args.len()), - calc_fn_hash(&func.name, func.args.len() + 1), + calc_fn_hash(None, &func.name, func.args.len()), + calc_fn_hash(None, &func.name, func.args.len() + 1), ); let new_lhs = BinaryExpr { @@ -2338,7 +2334,7 @@ impl Engine { settings.ensure_level_within_max_limit(state.max_expr_depth)?; let op = op_token.syntax(); - let hash = calc_fn_hash(&op, 2); + let hash = calc_fn_hash(None, &op, 2); let op_base = FnCallExpr { name: state.get_interned_string(op.as_ref()), @@ -2412,7 +2408,7 @@ impl Engine { // Convert into a call to `contains` FnCallExpr { - hashes: calc_fn_hash(OP_CONTAINS, 2).into(), + hashes: calc_fn_hash(None, OP_CONTAINS, 2).into(), args, name: state.get_interned_string(OP_CONTAINS), ..op_base @@ -2427,7 +2423,7 @@ impl Engine { .get(s.as_str()) .map_or(false, Option::is_some) => { - let hash = calc_fn_hash(&s, 2); + let hash = calc_fn_hash(None, &s, 2); let pos = args[0].start_position(); FnCallExpr { @@ -3345,7 +3341,7 @@ impl Engine { let func = func?; - let hash = calc_fn_hash(&func.name, func.params.len()); + let hash = calc_fn_hash(None, &func.name, func.params.len()); if !lib.is_empty() && lib.contains_key(&hash) { return Err(PERR::FnDuplicatedDefinition( @@ -3657,6 +3653,7 @@ impl Engine { let expr = FnCallExpr { name: state.get_interned_string(crate::engine::KEYWORD_FN_PTR_CURRY), hashes: FnCallHashes::from_native(calc_fn_hash( + None, crate::engine::KEYWORD_FN_PTR_CURRY, num_externals + 1, )), diff --git a/src/serde/metadata.rs b/src/serde/metadata.rs index 47b9d1f0..51011585 100644 --- a/src/serde/metadata.rs +++ b/src/serde/metadata.rs @@ -66,7 +66,7 @@ impl Ord for FnMetadata<'_> { impl<'a> From<&'a FuncInfo> for FnMetadata<'a> { fn from(info: &'a FuncInfo) -> Self { - let base_hash = calc_fn_hash(&info.name, info.num_params); + let base_hash = calc_fn_hash(None, &info.name, info.num_params); let (typ, full_hash) = if info.func.is_script() { (FnType::Script, base_hash) } else {