diff --git a/codegen/src/function.rs b/codegen/src/function.rs index e98785e7..a6cef77a 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -300,55 +300,50 @@ impl Parse for ExportedFn { let visibility = fn_all.vis; // Determine if the function requires a call context - if let Some(first_arg) = fn_all.sig.inputs.first() { - if let syn::FnArg::Typed(syn::PatType { ref ty, .. }) = first_arg { + match fn_all.sig.inputs.first() { + Some(syn::FnArg::Typed(syn::PatType { ref ty, .. })) => { match flatten_type_groups(ty.as_ref()) { syn::Type::Path(p) if p.path == context_type_path1 || p.path == context_type_path2 => { pass_context = true; } - _ => (), + _ => {} } } + _ => {} } let skip_slots = if pass_context { 1 } else { 0 }; // Determine whether function generates a special calling convention for a mutable receiver. - let mut_receiver = { - if let Some(first_arg) = fn_all.sig.inputs.iter().skip(skip_slots).next() { - match first_arg { - syn::FnArg::Receiver(syn::Receiver { - reference: Some(_), .. + let mut_receiver = match fn_all.sig.inputs.iter().skip(skip_slots).next() { + Some(syn::FnArg::Receiver(syn::Receiver { + reference: Some(_), .. + })) => true, + Some(syn::FnArg::Typed(syn::PatType { ref ty, .. })) => { + match flatten_type_groups(ty.as_ref()) { + syn::Type::Reference(syn::TypeReference { + mutability: Some(_), + .. }) => true, - syn::FnArg::Typed(syn::PatType { ref ty, .. }) => { - match flatten_type_groups(ty.as_ref()) { - syn::Type::Reference(syn::TypeReference { - mutability: Some(_), - .. - }) => true, - syn::Type::Reference(syn::TypeReference { - mutability: None, - ref elem, - .. - }) => match flatten_type_groups(elem.as_ref()) { - syn::Type::Path(ref p) if p.path == str_type_path => false, - _ => { - return Err(syn::Error::new( - ty.span(), - "references from Rhai in this position must be mutable", - )) - } - }, - _ => false, + syn::Type::Reference(syn::TypeReference { + mutability: None, + ref elem, + .. + }) => match flatten_type_groups(elem.as_ref()) { + syn::Type::Path(ref p) if p.path == str_type_path => false, + _ => { + return Err(syn::Error::new( + ty.span(), + "references from Rhai in this position must be mutable", + )) } - } + }, _ => false, } - } else { - false } + _ => false, }; // All arguments after the first must be moved except for &str. @@ -381,22 +376,25 @@ impl Parse for ExportedFn { } // Check return type. - if let syn::ReturnType::Type(_, ref ret_type) = fn_all.sig.output { - match flatten_type_groups(ret_type.as_ref()) { - syn::Type::Ptr(_) => { - return Err(syn::Error::new( - fn_all.sig.output.span(), - "Rhai functions cannot return pointers", - )) + match fn_all.sig.output { + syn::ReturnType::Type(_, ref ret_type) => { + match flatten_type_groups(ret_type.as_ref()) { + syn::Type::Ptr(_) => { + return Err(syn::Error::new( + fn_all.sig.output.span(), + "Rhai functions cannot return pointers", + )) + } + syn::Type::Reference(_) => { + return Err(syn::Error::new( + fn_all.sig.output.span(), + "Rhai functions cannot return references", + )) + } + _ => {} } - syn::Type::Reference(_) => { - return Err(syn::Error::new( - fn_all.sig.output.span(), - "Rhai functions cannot return references", - )) - } - _ => {} } + _ => {} } Ok(ExportedFn { entire_span, @@ -494,10 +492,9 @@ impl ExportedFn { } pub fn return_type(&self) -> Option<&syn::Type> { - if let syn::ReturnType::Type(_, ref ret_type) = self.signature.output { - Some(flatten_type_groups(ret_type)) - } else { - None + match self.signature.output { + syn::ReturnType::Type(_, ref ret_type) => Some(flatten_type_groups(ret_type)), + _ => None, } } @@ -622,16 +619,12 @@ impl ExportedFn { let arguments: Vec = dynamic_signature .inputs .iter() - .filter_map(|fn_arg| { - if let syn::FnArg::Typed(syn::PatType { ref pat, .. }) = fn_arg { - if let syn::Pat::Ident(ref ident) = pat.as_ref() { - Some(ident.ident.clone()) - } else { - None - } - } else { - None - } + .filter_map(|fn_arg| match fn_arg { + syn::FnArg::Typed(syn::PatType { ref pat, .. }) => match pat.as_ref() { + syn::Pat::Ident(ref ident) => Some(ident.ident.clone()), + _ => None, + }, + _ => None, }) .collect(); diff --git a/codegen/src/module.rs b/codegen/src/module.rs index ca740de1..df065797 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -156,8 +156,11 @@ impl Parse for Module { }) => { // #[cfg] attributes are not allowed on const declarations crate::attrs::deny_cfg_attr(&attrs)?; - if let syn::Visibility::Public(_) = vis { - consts.push((ident.to_string(), ty.clone(), expr.as_ref().clone())); + match vis { + syn::Visibility::Public(_) => { + consts.push((ident.to_string(), ty.clone(), expr.as_ref().clone())) + } + _ => {} } } _ => {} @@ -170,26 +173,23 @@ impl Parse for Module { sub_modules.reserve(content.len() - fns.len() - consts.len()); let mut i = 0; while i < content.len() { - if let syn::Item::Mod(_) = &content[i] { - let mut item_mod = match content.remove(i) { - syn::Item::Mod(m) => m, - _ => unreachable!(), - }; - let params: ExportedModParams = match crate::attrs::inner_item_attributes( - &mut item_mod.attrs, - "rhai_mod", - ) { - Ok(p) => p, - Err(e) => return Err(e), - }; - let module = - syn::parse2::(item_mod.to_token_stream()).and_then(|mut m| { - m.set_params(params)?; - Ok(m) - })?; - sub_modules.push(module); - } else { - i += 1; + match content[i] { + syn::Item::Mod(_) => { + let mut item_mod = match content.remove(i) { + syn::Item::Mod(m) => m, + _ => unreachable!(), + }; + let params: ExportedModParams = + crate::attrs::inner_item_attributes(&mut item_mod.attrs, "rhai_mod")?; + let module = syn::parse2::(item_mod.to_token_stream()).and_then( + |mut m| { + m.set_params(params)?; + Ok(m) + }, + )?; + sub_modules.push(module); + } + _ => i += 1, } } } else { diff --git a/src/ast.rs b/src/ast.rs index 5934ff34..17c981e0 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1513,7 +1513,7 @@ impl FloatWrapper { #[derive(Debug, Clone, Hash)] pub enum Expr { /// Dynamic constant. - /// Used to hold either an [`Array`] or [`Map`] literal for quick cloning. + /// Used to hold either an [`Array`] or [`Map`][crate::Map] literal for quick cloning. /// All other primitive data types should use the appropriate variants for better speed. DynamicConstant(Box, Position), /// Boolean constant. @@ -1855,7 +1855,7 @@ mod tests { assert_eq!(size_of::>(), 16); assert_eq!(size_of::(), 40); assert_eq!(size_of::>(), 40); - assert_eq!(size_of::(), 32); + assert_eq!(size_of::(), 80); assert_eq!(size_of::(), 288); assert_eq!(size_of::(), 56); assert_eq!(size_of::(), 16); diff --git a/src/engine.rs b/src/engine.rs index 5d9cba21..cab9bb17 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -997,11 +997,11 @@ impl Engine { // Check if the variable is `this` if name.as_str() == KEYWORD_THIS { - if let Some(val) = this_ptr { - return Ok(((*val).into(), *pos)); + return if let Some(val) = this_ptr { + Ok(((*val).into(), *pos)) } else { - return EvalAltResult::ErrorUnboundThis(*pos).into(); - } + EvalAltResult::ErrorUnboundThis(*pos).into() + }; } // Check if it is directly indexed diff --git a/src/engine_api.rs b/src/engine_api.rs index 36acc9ff..0a86a6b9 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -1232,7 +1232,7 @@ impl Engine { Self::read_file(path).and_then(|contents| Ok(self.compile_with_scope(scope, &contents)?)) } /// Parse a JSON string into an [object map][`Map`]. - /// This is a light-weight alternative to using, say, [`serde_json`][https://crates.io/crates/serde_json] to deserialize the JSON. + /// This is a light-weight alternative to using, say, [`serde_json`] to deserialize the JSON. /// /// The JSON string must be an object hash. It cannot be a simple scalar value. /// diff --git a/src/fn_args.rs b/src/fn_args.rs index 90a5d3f3..13dabf2f 100644 --- a/src/fn_args.rs +++ b/src/fn_args.rs @@ -26,7 +26,7 @@ pub trait FuncArgs { /// } /// /// impl FuncArgs for Options { - /// fn parse>(self, container: &mut C) { + /// fn parse>(self, container: &mut CONTAINER) { /// container.extend(std::iter::once(self.foo.into())); /// container.extend(std::iter::once(self.bar.into())); /// container.extend(std::iter::once(self.baz.into())); @@ -51,11 +51,12 @@ pub trait FuncArgs { /// # Ok(()) /// # } /// ``` - fn parse>(self, container: &mut T); + fn parse>(self, container: &mut CONTAINER); } impl FuncArgs for Vec { - fn parse>(self, container: &mut C) { + #[inline(always)] + fn parse>(self, container: &mut CONTAINER) { container.extend(self.into_iter().map(Variant::into_dynamic)); } } diff --git a/src/fn_call.rs b/src/fn_call.rs index 17356679..f55562ee 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -1132,13 +1132,10 @@ impl Engine { // Append the new curried arguments to the existing list. - args_expr.iter().skip(1).try_for_each( - |expr| -> Result<(), Box> { - fn_curry - .push(self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?); - Ok(()) - }, - )?; + args_expr.iter().skip(1).try_for_each(|expr| { + self.eval_expr(scope, mods, state, lib, this_ptr, expr, level) + .map(|value| fn_curry.push(value)) + })?; return Ok(FnPtr::new_unchecked(name, fn_curry).into()); } diff --git a/src/fn_native.rs b/src/fn_native.rs index 12cb94b6..0ad40f88 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -10,12 +10,11 @@ use crate::stdlib::{ iter::empty, mem, string::String, - vec::Vec, }; use crate::token::is_valid_identifier; use crate::{ calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ImmutableString, Module, Position, - RhaiResult, + RhaiResult, StaticVec, }; /// Trait that maps to `Send + Sync` only under the `sync` feature. @@ -251,7 +250,7 @@ pub type FnCallArgs<'a> = [&'a mut Dynamic]; /// A general function pointer, which may carry additional (i.e. curried) argument values /// to be passed onto a function during a call. #[derive(Debug, Clone)] -pub struct FnPtr(ImmutableString, Vec); +pub struct FnPtr(ImmutableString, StaticVec); impl FnPtr { /// Create a new function pointer. @@ -261,7 +260,10 @@ impl FnPtr { } /// Create a new function pointer without checking its parameters. #[inline(always)] - pub(crate) fn new_unchecked(name: impl Into, curry: Vec) -> Self { + pub(crate) fn new_unchecked( + name: impl Into, + curry: StaticVec, + ) -> Self { Self(name.into(), curry) } /// Get the name of the function. @@ -276,7 +278,7 @@ impl FnPtr { } /// Get the underlying data of the function pointer. #[inline(always)] - pub(crate) fn take_data(self) -> (ImmutableString, Vec) { + pub(crate) fn take_data(self) -> (ImmutableString, StaticVec) { (self.0, self.1) } /// Get the curried arguments. diff --git a/src/fn_register.rs b/src/fn_register.rs index 7d04bdb2..b4047a72 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -61,6 +61,8 @@ pub fn by_value(data: &mut Dynamic) -> T { /// Trait to register custom Rust functions. pub trait RegisterNativeFunction { + /// Convert this function into a [`CallableFunction`]. + fn into_callable_function(self) -> CallableFunction; /// Get the type ID's of this function's parameters. fn param_types() -> Box<[TypeId]>; /// Get the type names of this function's parameters. @@ -69,8 +71,6 @@ pub trait RegisterNativeFunction { fn return_type() -> TypeId; /// Get the type name of this function's return value. fn return_type_name() -> &'static str; - /// Convert this function into a [`CallableFunction`]. - fn into_callable_function(self) -> CallableFunction; } macro_rules! def_register { diff --git a/src/scope.rs b/src/scope.rs index 4ae73cbd..ac19bf2c 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -71,6 +71,7 @@ impl<'a> IntoIterator for Scope<'a> { type Item = (Cow<'a, str>, Dynamic); type IntoIter = Box + 'a>; + #[inline(always)] fn into_iter(self) -> Self::IntoIter { Box::new( self.values