diff --git a/src/eval/expr.rs b/src/eval/expr.rs index a0411410..2daa78e3 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -6,7 +6,7 @@ use crate::engine::{KEYWORD_THIS, OP_CONCAT}; use crate::eval::FnResolutionCacheEntry; use crate::func::{ calc_fn_params_hash, combine_hashes, gen_fn_call_signature, get_builtin_binary_op_fn, - CallableFunction, FnAny, + CallableFunction, }; use crate::types::dynamic::AccessMode; use crate::{Dynamic, Engine, Module, Position, RhaiResult, RhaiResultOf, Scope, ERR}; @@ -258,31 +258,39 @@ impl Engine { let cache = caches.fn_resolution_cache_mut(); - let func = if let Entry::Vacant(entry) = cache.entry(hash) { - let func = if args.len() == 2 { - get_builtin_binary_op_fn(&name, operands[0], operands[1]) - } else { - None - }; + let func = match cache.entry(hash) { + Entry::Vacant(entry) => { + let func = if args.len() == 2 { + get_builtin_binary_op_fn(name, operands[0], operands[1]) + } else { + None + }; - if let Some(f) = func { - entry.insert(Some(FnResolutionCacheEntry { - func: CallableFunction::from_method(Box::new(f) as Box), - source: None, - })); - &cache.get(&hash).unwrap().as_ref().unwrap().func - } else { - let result = self.exec_fn_call( - None, global, caches, lib, name, *hashes, operands, false, false, pos, - level, - ); - return result.map(|(v, ..)| v); + if let Some(f) = func { + &entry + .insert(Some(FnResolutionCacheEntry { + func: CallableFunction::from_fn_builtin(f), + source: None, + })) + .as_ref() + .unwrap() + .func + } else { + let result = self.exec_fn_call( + None, global, caches, lib, name, *hashes, operands, false, false, pos, + level, + ); + return result.map(|(v, ..)| v); + } + } + Entry::Occupied(entry) => { + if let Some(entry) = entry.into_mut() { + &entry.func + } else { + let sig = gen_fn_call_signature(self, name, operands); + return Err(ERR::ErrorFunctionNotFound(sig, pos).into()); + } } - } else if let Some(entry) = cache.get(&hash).unwrap() { - &entry.func - } else { - let sig = gen_fn_call_signature(self, name, operands); - return Err(ERR::ErrorFunctionNotFound(sig, pos).into()); }; let context = (self, name, None, &*global, lib, pos, level).into(); diff --git a/src/eval/target.rs b/src/eval/target.rs index e20f5b07..9c0804ab 100644 --- a/src/eval/target.rs +++ b/src/eval/target.rs @@ -253,7 +253,7 @@ impl<'a> Target<'a> { #[must_use] pub fn source(&self) -> &Dynamic { match self { - Self::RefMut(r) => *r, + Self::RefMut(r) => r, #[cfg(not(feature = "no_closure"))] Self::SharedValue { source, .. } => source, Self::TempValue(v) => v, @@ -401,9 +401,9 @@ impl Deref for Target<'_> { #[inline] fn deref(&self) -> &Dynamic { match self { - Self::RefMut(r) => *r, + Self::RefMut(r) => r, #[cfg(not(feature = "no_closure"))] - Self::SharedValue { source, .. } => &**source, + Self::SharedValue { source, .. } => source, Self::TempValue(ref r) => r, #[cfg(not(feature = "no_index"))] Self::Bit { ref value, .. } @@ -425,7 +425,7 @@ impl DerefMut for Target<'_> { #[inline] fn deref_mut(&mut self) -> &mut Dynamic { match self { - Self::RefMut(r) => *r, + Self::RefMut(r) => r, #[cfg(not(feature = "no_closure"))] Self::SharedValue { source, .. } => &mut *source, Self::TempValue(ref mut r) => r, diff --git a/src/func/call.rs b/src/func/call.rs index 8829fab7..17be540f 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -1,7 +1,6 @@ //! Implement function-calling mechanism for [`Engine`]. use super::callable_function::CallableFunction; -use super::native::FnAny; use super::{get_builtin_binary_op_fn, get_builtin_op_assignment_fn}; use crate::api::default_limits::MAX_DYNAMIC_PARAMETERS; use crate::ast::{Expr, FnCallHashes, Stmt}; @@ -289,18 +288,14 @@ impl Engine { get_builtin_op_assignment_fn(fn_name, *first_arg, rest_args[0]).map( |f| FnResolutionCacheEntry { - func: CallableFunction::from_method( - Box::new(f) as Box - ), + func: CallableFunction::from_fn_builtin(f), source: None, }, ) } else { get_builtin_binary_op_fn(fn_name, args[0], args[1]).map(|f| { FnResolutionCacheEntry { - func: CallableFunction::from_method( - Box::new(f) as Box - ), + func: CallableFunction::from_fn_builtin(f), source: None, } }) diff --git a/src/func/callable_function.rs b/src/func/callable_function.rs index 87691895..c08eb845 100644 --- a/src/func/callable_function.rs +++ b/src/func/callable_function.rs @@ -1,6 +1,6 @@ //! Module defining the standard Rhai function type. -use super::native::{FnAny, FnPlugin, IteratorFn, SendSync}; +use super::native::{FnAny, FnBuiltin, FnPlugin, IteratorFn, SendSync}; use crate::ast::FnAccess; use crate::plugin::PluginFunction; use crate::Shared; @@ -197,23 +197,17 @@ impl CallableFunction { Self::Script(..) => None, } } - /// Create a new [`CallableFunction::Pure`]. + /// Create a new [`CallableFunction::Method`] from `FnBuiltin`. #[inline(always)] #[must_use] - pub fn from_pure(func: Box) -> Self { - Self::Pure(func.into()) - } - /// Create a new [`CallableFunction::Method`]. - #[inline(always)] - #[must_use] - pub fn from_method(func: Box) -> Self { - Self::Method(func.into()) + pub fn from_fn_builtin(func: FnBuiltin) -> Self { + Self::Method(Shared::new(func)) } /// Create a new [`CallableFunction::Plugin`]. #[inline(always)] #[must_use] pub fn from_plugin(func: impl PluginFunction + 'static + SendSync) -> Self { - Self::Plugin((Box::new(func) as Box).into()) + Self::Plugin(Shared::new(func)) } } diff --git a/src/func/hashing.rs b/src/func/hashing.rs index e81cabdd..2a5f5dcc 100644 --- a/src/func/hashing.rs +++ b/src/func/hashing.rs @@ -96,18 +96,15 @@ pub fn get_hasher() -> ahash::AHasher { #[inline] #[must_use] pub fn calc_qualified_var_hash<'a>( - modules: impl IntoIterator, + modules: impl IntoIterator>, var_name: &str, ) -> u64 { let s = &mut get_hasher(); // We always skip the first module - let mut len = 0; - modules - .into_iter() - .inspect(|_| len += 1) - .skip(1) - .for_each(|m| m.hash(s)); + let iter = modules.into_iter(); + let len = iter.len(); + iter.skip(1).for_each(|m| m.hash(s)); len.hash(s); var_name.hash(s); @@ -133,19 +130,16 @@ pub fn calc_qualified_var_hash<'a>( #[inline] #[must_use] pub fn calc_qualified_fn_hash<'a>( - modules: impl IntoIterator, + modules: impl IntoIterator>, fn_name: &str, num: usize, ) -> u64 { let s = &mut get_hasher(); // We always skip the first module - let mut len = 0; - modules - .into_iter() - .inspect(|_| len += 1) - .skip(1) - .for_each(|m| m.hash(s)); + let iter = modules.into_iter(); + let len = iter.len(); + iter.skip(1).for_each(|m| m.hash(s)); len.hash(s); fn_name.hash(s); num.hash(s); @@ -179,11 +173,13 @@ pub fn calc_fn_hash(fn_name: &str, num: usize) -> u64 { /// If the hash happens to be zero, it is mapped to `DEFAULT_HASH`. #[inline] #[must_use] -pub fn calc_fn_params_hash(params: impl IntoIterator) -> u64 { +pub fn calc_fn_params_hash( + params: impl IntoIterator>, +) -> u64 { let s = &mut get_hasher(); - let mut len = 0; - params.into_iter().for_each(|t| { - len += 1; + let iter = params.into_iter(); + let len = iter.len(); + iter.for_each(|t| { t.hash(s); }); len.hash(s); diff --git a/src/func/register.rs b/src/func/register.rs index c282399f..b1fed5bd 100644 --- a/src/func/register.rs +++ b/src/func/register.rs @@ -4,7 +4,7 @@ use super::call::FnCallArgs; use super::callable_function::CallableFunction; -use super::native::{FnAny, SendSync}; +use super::native::{SendSync, Shared}; use crate::types::dynamic::{DynamicWriteLock, Variant}; use crate::{reify, Dynamic, NativeCallContext, RhaiResultOf}; #[cfg(feature = "no_std")] @@ -120,7 +120,7 @@ macro_rules! check_constant { macro_rules! def_register { () => { - def_register!(imp from_pure :); + def_register!(imp Pure :); }; (imp $abi:ident : $($par:ident => $arg:expr => $mark:ty => $param:ty => $let:stmt => $clone:expr),*) => { // ^ function ABI type @@ -140,7 +140,7 @@ macro_rules! def_register { #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::() } #[inline(always)] fn into_callable_function(self) -> CallableFunction { - CallableFunction::$abi(Box::new(move |_ctx: NativeCallContext, args: &mut FnCallArgs| { + CallableFunction::$abi(Shared::new(move |_ctx: NativeCallContext, args: &mut FnCallArgs| { // The arguments are assumed to be of the correct number and types! check_constant!(_ctx, args); @@ -152,7 +152,7 @@ macro_rules! def_register { // Map the result Ok(Dynamic::from(r)) - }) as Box) + })) } } @@ -166,7 +166,7 @@ macro_rules! def_register { #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::() } #[inline(always)] fn into_callable_function(self) -> CallableFunction { - CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { + CallableFunction::$abi(Shared::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { // The arguments are assumed to be of the correct number and types! check_constant!(ctx, args); @@ -178,7 +178,7 @@ macro_rules! def_register { // Map the result Ok(Dynamic::from(r)) - }) as Box) + })) } } @@ -192,7 +192,7 @@ macro_rules! def_register { #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::>() } #[inline(always)] fn into_callable_function(self) -> CallableFunction { - CallableFunction::$abi(Box::new(move |_ctx: NativeCallContext, args: &mut FnCallArgs| { + CallableFunction::$abi(Shared::new(move |_ctx: NativeCallContext, args: &mut FnCallArgs| { // The arguments are assumed to be of the correct number and types! check_constant!(_ctx, args); @@ -201,7 +201,7 @@ macro_rules! def_register { // Call the function with each argument value self($($arg),*).map(Dynamic::from) - }) as Box) + })) } } @@ -215,7 +215,7 @@ macro_rules! def_register { #[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::>() } #[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::>() } #[inline(always)] fn into_callable_function(self) -> CallableFunction { - CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { + CallableFunction::$abi(Shared::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { // The arguments are assumed to be of the correct number and types! check_constant!(ctx, args); @@ -224,15 +224,15 @@ macro_rules! def_register { // Call the function with each argument value self(ctx, $($arg),*).map(Dynamic::from) - }) as Box) + })) } } //def_register!(imp_pop $($par => $mark => $param),*); }; ($p0:ident $(, $p:ident)*) => { - def_register!(imp from_pure : $p0 => $p0 => $p0 => $p0 => let $p0 => by_value $(, $p => $p => $p => $p => let $p => by_value)*); - def_register!(imp from_method : $p0 => &mut $p0 => Mut<$p0> => &mut $p0 => let mut $p0 => by_ref $(, $p => $p => $p => $p => let $p => by_value)*); + def_register!(imp Pure : $p0 => $p0 => $p0 => $p0 => let $p0 => by_value $(, $p => $p => $p => $p => let $p => by_value)*); + def_register!(imp Method : $p0 => &mut $p0 => Mut<$p0> => &mut $p0 => let mut $p0 => by_ref $(, $p => $p => $p => $p => let $p => by_value)*); // ^ CallableFunction constructor // ^ first parameter passed through // ^ others passed by value (by_value) diff --git a/src/module/mod.rs b/src/module/mod.rs index 5d897e01..16a10dfa 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -239,7 +239,7 @@ impl FuncInfo { /// The first module name is skipped. Hashing starts from the _second_ module in the chain. #[inline] pub fn calc_native_fn_hash<'a>( - modules: impl IntoIterator, + modules: impl IntoIterator>, fn_name: &str, params: &[TypeId], ) -> u64 { @@ -1263,7 +1263,7 @@ impl Module { access, None, arg_types, - CallableFunction::from_method(Box::new(f)), + CallableFunction::Method(Shared::new(f)), ) }