diff --git a/CHANGELOG.md b/CHANGELOG.md index 87f55f4b..59875fda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,31 @@ Rhai Release Notes ================== +Version 1.2.0 +============= + +New features +------------ + +* `#[cfg(...)]` attributes can now be put directly on plugin functions or function defined in a plugin module. + +Enhancements +------------ + +* Array methods now avoid cloning as much as possible (although most predicates will involve cloning anyway if passed a closure). +* Array methods that take function pointers (e.g. closures) now optionally take the function name as a string. +* Array adds the `dedup` method. +* Array adds a `sort` method with no parameters which sorts homogeneous arrays of built-in comparable types (e.g. `INT`). +* Inlining is disabled for error-path functions because errors are exceptional and scripts usually fail completely when an error is encountered. +* The `optimize` module is completely eliminated under `no_optimize`, which should yield smaller code size. + +Deprecated API's +---------------- + +* `NativeCallContext::call_fn_dynamic_raw` is deprecated and `NativeCallContext::call_fn_raw` is added. +* `From` for `Result>` is deprecated so it will no longer be possible to do `EvalAltResult::ErrorXXXXX.into()` to convert to a `Result`; instead, `Err(EvalAltResult:ErrorXXXXX.into())` must be used. Code is clearer if errors are explicitly wrapped in `Err`. + + Version 1.1.0 ============= @@ -60,10 +85,6 @@ Enhancements * `StaticVec` is changed to keep three items inline instead of four. -Version 1.0.7 -============= - - Version 1.0.6 ============= diff --git a/Cargo.toml b/Cargo.toml index 52e61ab6..cc04ffed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "codegen"] [package] name = "rhai" -version = "1.1.0" +version = "1.2.0" edition = "2018" authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"] description = "Embedded scripting for Rust" @@ -20,7 +20,7 @@ smallvec = { version = "1.6", default-features = false, features = ["union"] } ahash = { version = "0.7", default-features = false } num-traits = { version = "0.2", default-features = false } smartstring = { version = "0.2.7", default-features = false } -rhai_codegen = { version = "1.0", path = "codegen", default-features = false } +rhai_codegen = { version = "1.1", path = "codegen", default-features = false } [features] default = ["ahash/std", "num-traits/std"] diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 854ad08a..472c5ca1 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rhai_codegen" -version = "1.1.0" +version = "1.2.0" edition = "2018" authors = ["jhwgh1968", "Stephen Chung"] description = "Procedural macros support package for Rhai, a scripting language and engine for Rust" @@ -16,7 +16,7 @@ default = [] metadata = [] [dev-dependencies] -rhai = { path = "..", version = "1" } +rhai = { path = "..", version = "1.1" } trybuild = "1" [dependencies] diff --git a/codegen/src/attrs.rs b/codegen/src/attrs.rs index 7ffdae87..977e73de 100644 --- a/codegen/src/attrs.rs +++ b/codegen/src/attrs.rs @@ -1,3 +1,4 @@ +use proc_macro2::{Ident, Span, TokenStream}; use syn::{ parse::{ParseStream, Parser}, spanned::Spanned, @@ -24,14 +25,14 @@ pub trait ExportedParams: Sized { #[derive(Debug, Clone)] pub struct AttrItem { - pub key: proc_macro2::Ident, + pub key: Ident, pub value: Option, - pub span: proc_macro2::Span, + pub span: Span, } #[derive(Debug, Clone)] pub struct ExportInfo { - pub item_span: proc_macro2::Span, + pub item_span: Span, pub items: Vec, } @@ -42,8 +43,7 @@ pub fn parse_attr_items(args: ParseStream) -> syn::Result { items: Vec::new(), }); } - let arg_list = args - .call(syn::punctuated::Punctuated::::parse_separated_nonempty)?; + let arg_list = args.call(syn::punctuated::Punctuated::parse_separated_nonempty)?; parse_punctuated_items(arg_list) } @@ -53,7 +53,8 @@ pub fn parse_punctuated_items( ) -> syn::Result { let list_span = arg_list.span(); - let mut attrs: Vec = Vec::new(); + let mut attrs = Vec::new(); + for arg in arg_list { let arg_span = arg.span(); let (key, value) = match arg { @@ -62,7 +63,7 @@ pub fn parse_punctuated_items( ref right, .. }) => { - let attr_name: syn::Ident = match left.as_ref() { + let attr_name = match left.as_ref() { syn::Expr::Path(syn::ExprPath { path: attr_path, .. }) => attr_path.get_ident().cloned().ok_or_else(|| { @@ -79,13 +80,11 @@ pub fn parse_punctuated_items( }; (attr_name, Some(attr_value)) } - syn::Expr::Path(syn::ExprPath { - path: attr_path, .. - }) => attr_path + syn::Expr::Path(syn::ExprPath { path, .. }) => path .get_ident() .cloned() .map(|a| (a, None)) - .ok_or_else(|| syn::Error::new(attr_path.span(), "expecting attribute name"))?, + .ok_or_else(|| syn::Error::new(path.span(), "expecting attribute name"))?, x => return Err(syn::Error::new(x.span(), "expecting identifier")), }; attrs.push(AttrItem { @@ -102,18 +101,16 @@ pub fn parse_punctuated_items( } pub fn outer_item_attributes( - args: proc_macro2::TokenStream, + args: TokenStream, _attr_name: &str, ) -> syn::Result { if args.is_empty() { return Ok(T::no_attrs()); } - let parser = syn::punctuated::Punctuated::::parse_separated_nonempty; - let arg_list = parser.parse2(args)?; + let arg_list = syn::punctuated::Punctuated::parse_separated_nonempty.parse2(args)?; - let export_info = parse_punctuated_items(arg_list)?; - T::from_info(export_info) + T::from_info(parse_punctuated_items(arg_list)?) } pub fn inner_item_attributes( @@ -132,16 +129,10 @@ pub fn inner_item_attributes( } } -pub fn deny_cfg_attr(attrs: &[syn::Attribute]) -> syn::Result<()> { - if let Some(cfg_attr) = attrs +pub fn collect_cfg_attr(attrs: &[syn::Attribute]) -> Vec { + attrs .iter() - .find(|a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false)) - { - Err(syn::Error::new( - cfg_attr.span(), - "cfg attributes not allowed on this item", - )) - } else { - Ok(()) - } + .filter(|&a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false)) + .cloned() + .collect() } diff --git a/codegen/src/function.rs b/codegen/src/function.rs index 3158cb33..5e70c8c8 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -1,3 +1,10 @@ +use proc_macro2::{Span, TokenStream}; +use quote::{quote, quote_spanned, ToTokens}; +use syn::{ + parse::{Parse, ParseStream}, + spanned::Spanned, +}; + #[cfg(no_std)] use alloc::format; #[cfg(not(no_std))] @@ -5,12 +12,6 @@ use std::format; use std::borrow::Cow; -use quote::{quote, quote_spanned, ToTokens}; -use syn::{ - parse::{Parse, ParseStream}, - spanned::Spanned, -}; - use crate::attrs::{ExportInfo, ExportScope, ExportedParams}; #[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)] @@ -52,7 +53,7 @@ impl Default for FnSpecialAccess { } impl FnSpecialAccess { - pub fn get_fn_name(&self) -> Option<(String, String, proc_macro2::Span)> { + pub fn get_fn_name(&self) -> Option<(String, String, Span)> { match self { FnSpecialAccess::None => None, FnSpecialAccess::Property(Property::Get(ref g)) => { @@ -64,12 +65,12 @@ impl FnSpecialAccess { FnSpecialAccess::Index(Index::Get) => Some(( FN_IDX_GET.to_string(), "index_get".to_string(), - proc_macro2::Span::call_site(), + Span::call_site(), )), FnSpecialAccess::Index(Index::Set) => Some(( FN_IDX_SET.to_string(), "index_set".to_string(), - proc_macro2::Span::call_site(), + Span::call_site(), )), } } @@ -98,12 +99,12 @@ pub fn print_type(ty: &syn::Type) -> String { #[derive(Debug, Default)] pub struct ExportedFnParams { pub name: Vec, - pub return_raw: Option, - pub pure: Option, + pub return_raw: Option, + pub pure: Option, pub skip: bool, pub special: FnSpecialAccess, pub namespace: FnNamespaceAccess, - pub span: Option, + pub span: Option, } pub const FN_GET: &str = "get$"; @@ -274,12 +275,13 @@ impl ExportedParams for ExportedFnParams { #[derive(Debug)] pub struct ExportedFn { - entire_span: proc_macro2::Span, + entire_span: Span, signature: syn::Signature, visibility: syn::Visibility, pass_context: bool, mut_receiver: bool, params: ExportedFnParams, + cfg_attrs: Vec, } impl Parse for ExportedFn { @@ -293,8 +295,7 @@ impl Parse for ExportedFn { syn::parse2::(quote! { rhai::NativeCallContext }).unwrap(); let mut pass_context = false; - // #[cfg] attributes are not allowed on functions due to what is generated for them - crate::attrs::deny_cfg_attr(&fn_all.attrs)?; + let cfg_attrs = crate::attrs::collect_cfg_attr(&fn_all.attrs); let visibility = fn_all.vis; @@ -369,7 +370,7 @@ impl Parse for ExportedFn { if !is_ok { return Err(syn::Error::new( ty.span(), - "this type in this position passes from Rhai by value", + "function parameters other than the first one cannot be passed by reference", )); } } @@ -402,6 +403,7 @@ impl Parse for ExportedFn { pass_context, mut_receiver, params: Default::default(), + cfg_attrs, }) } } @@ -413,6 +415,10 @@ impl ExportedFn { &self.params } + pub fn cfg_attrs(&self) -> &[syn::Attribute] { + &self.cfg_attrs + } + pub fn update_scope(&mut self, parent_scope: &ExportScope) { let keep = match (self.params.skip, parent_scope) { (true, _) => false, @@ -443,7 +449,7 @@ impl ExportedFn { !matches!(self.visibility, syn::Visibility::Inherited) } - pub fn span(&self) -> &proc_macro2::Span { + pub fn span(&self) -> &Span { &self.entire_span } @@ -456,7 +462,7 @@ impl ExportedFn { .params .name .iter() - .map(|s| syn::LitStr::new(s, proc_macro2::Span::call_site())) + .map(|s| syn::LitStr::new(s, Span::call_site())) .collect(); if let Some((s, _, span)) = self.params.special.get_fn_name() { @@ -497,6 +503,10 @@ impl ExportedFn { } } + pub fn set_cfg_attrs(&mut self, cfg_attrs: Vec) { + self.cfg_attrs = cfg_attrs + } + pub fn set_params(&mut self, mut params: ExportedFnParams) -> syn::Result<()> { // Several issues are checked here to avoid issues with diagnostics caused by raising them later. // @@ -586,7 +596,7 @@ impl ExportedFn { Ok(()) } - pub fn generate(self) -> proc_macro2::TokenStream { + pub fn generate(self) -> TokenStream { let name: syn::Ident = syn::Ident::new(&format!("rhai_fn_{}", self.name()), self.name().span()); let impl_block = self.generate_impl("Token"); @@ -603,17 +613,16 @@ impl ExportedFn { } } - pub fn generate_dynamic_fn(&self) -> proc_macro2::TokenStream { + pub fn generate_dynamic_fn(&self) -> TokenStream { let name = self.name().clone(); let mut dynamic_signature = self.signature.clone(); - dynamic_signature.ident = - syn::Ident::new("dynamic_result_fn", proc_macro2::Span::call_site()); + dynamic_signature.ident = syn::Ident::new("dynamic_result_fn", Span::call_site()); dynamic_signature.output = syn::parse2::(quote! { -> RhaiResult }) .unwrap(); - let arguments: Vec = dynamic_signature + let arguments: Vec<_> = dynamic_signature .inputs .iter() .filter_map(|fn_arg| match fn_arg { @@ -628,7 +637,7 @@ impl ExportedFn { let return_span = self .return_type() .map(|r| r.span()) - .unwrap_or_else(proc_macro2::Span::call_site); + .unwrap_or_else(Span::call_site); if self.params.return_raw.is_some() { quote_spanned! { return_span => pub #dynamic_signature { @@ -646,16 +655,16 @@ impl ExportedFn { } } - pub fn generate_impl(&self, on_type_name: &str) -> proc_macro2::TokenStream { + pub fn generate_impl(&self, on_type_name: &str) -> TokenStream { let sig_name = self.name().clone(); let arg_count = self.arg_count(); let is_method_call = self.mutable_receiver(); - let mut unpack_statements: Vec = Vec::new(); - let mut unpack_exprs: Vec = Vec::new(); + let mut unpack_statements = Vec::new(); + let mut unpack_exprs = Vec::new(); #[cfg(feature = "metadata")] - let mut input_type_names: Vec = Vec::new(); - let mut input_type_exprs: Vec = Vec::new(); + let mut input_type_names = Vec::new(); + let mut input_type_exprs = Vec::new(); let return_type = self .return_type() @@ -672,7 +681,7 @@ impl ExportedFn { if is_method_call { skip_first_arg = true; let first_arg = self.arg_list().next().unwrap(); - let var = syn::Ident::new("arg0", proc_macro2::Span::call_site()); + let var = syn::Ident::new("arg0", Span::call_site()); match first_arg { syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => { #[cfg(feature = "metadata")] @@ -696,7 +705,7 @@ impl ExportedFn { unpack_statements.push( syn::parse2::(quote! { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant(#arg_lit_str.to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant(#arg_lit_str.to_string(), Position::NONE).into()); } }) .unwrap(), @@ -725,7 +734,7 @@ impl ExportedFn { let str_type_path = syn::parse2::(quote! { str }).unwrap(); let string_type_path = syn::parse2::(quote! { String }).unwrap(); for (i, arg) in self.arg_list().enumerate().skip(skip_first_arg as usize) { - let var = syn::Ident::new(&format!("arg{}", i), proc_macro2::Span::call_site()); + let var = syn::Ident::new(&format!("arg{}", i), Span::call_site()); let is_string; let is_ref; match arg { @@ -811,7 +820,7 @@ impl ExportedFn { let return_span = self .return_type() .map(|r| r.span()) - .unwrap_or_else(proc_macro2::Span::call_site); + .unwrap_or_else(Span::call_site); let return_expr = if self.params.return_raw.is_none() { quote_spanned! { return_span => Ok(Dynamic::from(#sig_name(#(#unpack_exprs),*))) @@ -822,7 +831,7 @@ impl ExportedFn { } }; - let type_name = syn::Ident::new(on_type_name, proc_macro2::Span::call_site()); + let type_name = syn::Ident::new(on_type_name, Span::call_site()); #[cfg(feature = "metadata")] let param_names = quote! { @@ -831,11 +840,19 @@ impl ExportedFn { #[cfg(not(feature = "metadata"))] let param_names = quote! {}; + let cfg_attrs: Vec<_> = self + .cfg_attrs() + .iter() + .map(syn::Attribute::to_token_stream) + .collect(); + quote! { + #(#cfg_attrs)* impl #type_name { #param_names #[inline(always)] pub fn param_types() -> [TypeId; #arg_count] { [#(#input_type_exprs),*] } } + #(#cfg_attrs)* impl PluginFunction for #type_name { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index a0005864..3be27449 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -88,7 +88,7 @@ //! use quote::quote; -use syn::parse_macro_input; +use syn::{parse_macro_input, spanned::Spanned}; mod attrs; mod function; @@ -130,9 +130,19 @@ pub fn export_fn( let parsed_params = match crate::attrs::outer_item_attributes(args.into(), "export_fn") { Ok(args) => args, - Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()), + Err(err) => return err.to_compile_error().into(), }; let mut function_def = parse_macro_input!(input as function::ExportedFn); + + if !function_def.cfg_attrs().is_empty() { + return syn::Error::new( + function_def.cfg_attrs()[0].span(), + "`cfg` attributes are not allowed for `export_fn`", + ) + .to_compile_error() + .into(); + } + if let Err(e) = function_def.set_params(parsed_params) { return e.to_compile_error().into(); } @@ -173,7 +183,7 @@ pub fn export_module( ) -> proc_macro::TokenStream { let parsed_params = match crate::attrs::outer_item_attributes(args.into(), "export_module") { Ok(args) => args, - Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()), + Err(err) => return err.to_compile_error().into(), }; let mut module_def = parse_macro_input!(input as module::Module); if let Err(e) = module_def.set_params(parsed_params) { diff --git a/codegen/src/module.rs b/codegen/src/module.rs index c5d20b51..75099218 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -1,14 +1,6 @@ use quote::{quote, ToTokens}; use syn::{parse::Parse, parse::ParseStream}; -use crate::function::ExportedFn; -use crate::rhai_module::ExportedConst; - -#[cfg(no_std)] -use alloc::vec as new_vec; -#[cfg(not(no_std))] -use std::vec as new_vec; - #[cfg(no_std)] use core::mem; #[cfg(not(no_std))] @@ -17,7 +9,8 @@ use std::mem; use std::borrow::Cow; use crate::attrs::{AttrItem, ExportInfo, ExportScope, ExportedParams}; -use crate::function::ExportedFnParams; +use crate::function::ExportedFn; +use crate::rhai_module::ExportedConst; #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] pub struct ExportedModParams { @@ -32,9 +25,7 @@ impl Parse for ExportedModParams { return Ok(ExportedModParams::default()); } - let info = crate::attrs::parse_attr_items(args)?; - - Self::from_info(info) + Self::from_info(crate::attrs::parse_attr_items(args)?) } } @@ -115,8 +106,9 @@ impl Parse for Module { fn parse(input: ParseStream) -> syn::Result { let mut mod_all: syn::ItemMod = input.parse()?; let fns: Vec<_>; - let mut consts: Vec<_> = new_vec![]; - let mut sub_modules: Vec<_> = Vec::new(); + let mut consts = Vec::new(); + let mut sub_modules = Vec::new(); + if let Some((_, ref mut content)) = mod_all.content { // Gather and parse functions. fns = content @@ -126,17 +118,13 @@ impl Parse for Module { _ => None, }) .try_fold(Vec::new(), |mut vec, item_fn| { - // #[cfg] attributes are not allowed on functions - crate::attrs::deny_cfg_attr(&item_fn.attrs)?; + let params = + crate::attrs::inner_item_attributes(&mut item_fn.attrs, "rhai_fn")?; - let params: ExportedFnParams = - match crate::attrs::inner_item_attributes(&mut item_fn.attrs, "rhai_fn") { - Ok(p) => p, - Err(e) => return Err(e), - }; syn::parse2::(item_fn.to_token_stream()) .and_then(|mut f| { f.set_params(params)?; + f.set_cfg_attrs(crate::attrs::collect_cfg_attr(&item_fn.attrs)); Ok(f) }) .map(|f| vec.push(f)) @@ -152,16 +140,12 @@ impl Parse for Module { attrs, ty, .. - }) => { - // #[cfg] attributes are not allowed on const declarations - crate::attrs::deny_cfg_attr(&attrs)?; - match vis { - syn::Visibility::Public(_) => { - consts.push((ident.to_string(), ty.clone(), expr.as_ref().clone())) - } - _ => {} - } - } + }) if matches!(vis, syn::Visibility::Public(_)) => consts.push(( + ident.to_string(), + ty.clone(), + expr.as_ref().clone(), + crate::attrs::collect_cfg_attr(&attrs), + )), _ => {} } } @@ -192,7 +176,7 @@ impl Parse for Module { } } } else { - fns = new_vec![]; + fns = Vec::new(); } Ok(Module { mod_all, @@ -205,7 +189,7 @@ impl Parse for Module { } impl Module { - pub fn attrs(&self) -> &Vec { + pub fn attrs(&self) -> &[syn::Attribute] { &self.mod_all.attrs } @@ -273,10 +257,12 @@ impl Module { // NB: sub-modules must have their new items for exporting generated in depth-first order // to avoid issues caused by re-parsing them - let inner_modules: Vec = sub_modules.drain(..) - .try_fold::, _, - Result, syn::Error>>( - Vec::new(), |mut acc, m| { acc.push(m.generate_inner()?); Ok(acc) })?; + let inner_modules = sub_modules + .drain(..) + .try_fold::<_, _, Result<_, syn::Error>>(Vec::new(), |mut acc, m| { + acc.push(m.generate_inner()?); + Ok(acc) + })?; // Regenerate the module with the new content added. Ok(quote! { @@ -319,7 +305,7 @@ impl Module { } #[allow(dead_code)] - pub fn content(&self) -> Option<&Vec> { + pub fn content(&self) -> Option<&[syn::Item]> { match self.mod_all { syn::ItemMod { content: Some((_, ref vec)), diff --git a/codegen/src/register.rs b/codegen/src/register.rs index 5813e2c1..773711c9 100644 --- a/codegen/src/register.rs +++ b/codegen/src/register.rs @@ -22,10 +22,11 @@ type RegisterMacroInput = (syn::Expr, proc_macro2::TokenStream, syn::Path); pub fn parse_register_macro( args: proc_macro::TokenStream, ) -> Result { - let parser = syn::punctuated::Punctuated::::parse_separated_nonempty; - let args = parser.parse(args).unwrap(); + let args = syn::punctuated::Punctuated::<_, syn::Token![,]>::parse_separated_nonempty + .parse(args) + .unwrap(); let arg_span = args.span(); - let mut items: Vec = args.into_iter().collect(); + let mut items: Vec<_> = args.into_iter().collect(); if items.len() != 3 { return Err(syn::Error::new( arg_span, diff --git a/codegen/src/rhai_module.rs b/codegen/src/rhai_module.rs index f3137f78..a16eab56 100644 --- a/codegen/src/rhai_module.rs +++ b/codegen/src/rhai_module.rs @@ -1,6 +1,7 @@ -use std::collections::BTreeMap; +use proc_macro2::{Span, TokenStream}; +use quote::{quote, ToTokens}; -use quote::quote; +use std::collections::BTreeMap; use crate::attrs::ExportScope; use crate::function::{ @@ -9,26 +10,33 @@ use crate::function::{ }; use crate::module::Module; -pub type ExportedConst = (String, Box, syn::Expr); +pub type ExportedConst = (String, Box, syn::Expr, Vec); pub fn generate_body( fns: &mut [ExportedFn], consts: &[ExportedConst], sub_modules: &mut [Module], parent_scope: &ExportScope, -) -> proc_macro2::TokenStream { - let mut set_fn_statements: Vec = Vec::new(); - let mut set_const_statements: Vec = Vec::new(); - let mut add_mod_blocks: Vec = Vec::new(); - let mut set_flattened_mod_blocks: Vec = Vec::new(); +) -> TokenStream { + let mut set_fn_statements = Vec::new(); + let mut set_const_statements = Vec::new(); + let mut add_mod_blocks = Vec::new(); + let mut set_flattened_mod_blocks = Vec::new(); let str_type_path = syn::parse2::(quote! { str }).unwrap(); let string_type_path = syn::parse2::(quote! { String }).unwrap(); - for (const_name, _, _) in consts { - let const_literal = syn::LitStr::new(&const_name, proc_macro2::Span::call_site()); - let const_ref = syn::Ident::new(&const_name, proc_macro2::Span::call_site()); + for (const_name, _, _, cfg_attrs) in consts { + let const_literal = syn::LitStr::new(&const_name, Span::call_site()); + let const_ref = syn::Ident::new(&const_name, Span::call_site()); + + let cfg_attrs: Vec<_> = cfg_attrs + .iter() + .map(syn::Attribute::to_token_stream) + .collect(); + set_const_statements.push( syn::parse2::(quote! { + #(#cfg_attrs)* m.set_var(#const_literal, #const_ref); }) .unwrap(), @@ -41,15 +49,8 @@ pub fn generate_body( continue; } let module_name = item_mod.module_name(); - let exported_name: syn::LitStr = syn::LitStr::new( - item_mod.exported_name().as_ref(), - proc_macro2::Span::call_site(), - ); - let cfg_attrs: Vec<&syn::Attribute> = item_mod - .attrs() - .iter() - .filter(|&a| a.path.get_ident().map(|i| *i == "cfg").unwrap_or(false)) - .collect(); + let exported_name = syn::LitStr::new(item_mod.exported_name().as_ref(), Span::call_site()); + let cfg_attrs = crate::attrs::collect_cfg_attr(item_mod.attrs()); add_mod_blocks.push( syn::parse2::(quote! { { @@ -71,19 +72,20 @@ pub fn generate_body( } // NB: these are token streams, because re-parsing messes up "> >" vs ">>" - let mut gen_fn_tokens: Vec = Vec::new(); + let mut gen_fn_tokens = Vec::new(); + for function in fns { function.update_scope(&parent_scope); if function.skipped() { continue; } let fn_token_name = syn::Ident::new( - &format!("{}_token", function.name().to_string()), + &format!("{}_token", function.name()), function.name().span(), ); let reg_names = function.exported_names(); - let fn_input_types: Vec = function + let fn_input_types: Vec<_> = function .arg_list() .map(|fn_arg| match fn_arg { syn::FnArg::Receiver(_) => panic!("internal error: receiver fn outside impl!?"), @@ -126,6 +128,12 @@ pub fn generate_body( }) .collect(); + let cfg_attrs: Vec<_> = function + .cfg_attrs() + .iter() + .map(syn::Attribute::to_token_stream) + .collect(); + for fn_literal in reg_names { let mut namespace = FnNamespaceAccess::Internal; @@ -166,6 +174,7 @@ pub fn generate_body( set_fn_statements.push( syn::parse2::(quote! { + #(#cfg_attrs)* m.set_fn(#fn_literal, FnNamespace::#ns_str, FnAccess::Public, #param_names, &[#(#fn_input_types),*], #fn_token_name().into()); }) @@ -174,9 +183,11 @@ pub fn generate_body( } gen_fn_tokens.push(quote! { + #(#cfg_attrs)* #[allow(non_camel_case_types)] pub struct #fn_token_name(); }); + gen_fn_tokens.push(function.generate_impl(&fn_token_name.to_string())); } @@ -229,8 +240,8 @@ pub fn check_rename_collisions(fns: &[ExportedFn]) -> Result<(), syn::Error> { }) } - let mut renames = BTreeMap::::new(); - let mut fn_defs = BTreeMap::::new(); + let mut renames = BTreeMap::new(); + let mut fn_defs = BTreeMap::new(); for item_fn in fns.iter() { if !item_fn.params().name.is_empty() || item_fn.params().special != FnSpecialAccess::None { @@ -251,11 +262,11 @@ pub fn check_rename_collisions(fns: &[ExportedFn]) -> Result<(), syn::Error> { if let Some(other_span) = renames.insert(key, current_span) { let mut err = syn::Error::new( current_span, - format!("duplicate Rhai signature for '{}'", &fn_name), + format!("duplicate Rhai signature for '{}'", fn_name), ); err.combine(syn::Error::new( other_span, - format!("duplicated function renamed '{}'", &fn_name), + format!("duplicated function renamed '{}'", fn_name), )); return Err(err); } @@ -263,13 +274,11 @@ pub fn check_rename_collisions(fns: &[ExportedFn]) -> Result<(), syn::Error> { } else { let ident = item_fn.name(); if let Some(other_span) = fn_defs.insert(ident.to_string(), ident.span()) { - let mut err = syn::Error::new( - ident.span(), - format!("duplicate function '{}'", ident.to_string()), - ); + let mut err = + syn::Error::new(ident.span(), format!("duplicate function '{}'", ident)); err.combine(syn::Error::new( other_span, - format!("duplicated function '{}'", ident.to_string()), + format!("duplicated function '{}'", ident), )); return Err(err); } @@ -277,11 +286,11 @@ pub fn check_rename_collisions(fns: &[ExportedFn]) -> Result<(), syn::Error> { if let Some(fn_span) = renames.get(&key) { let mut err = syn::Error::new( ident.span(), - format!("duplicate Rhai signature for '{}'", &ident), + format!("duplicate Rhai signature for '{}'", ident), ); err.combine(syn::Error::new( *fn_span, - format!("duplicated function '{}'", &ident), + format!("duplicated function '{}'", ident), )); return Err(err); } diff --git a/codegen/src/test/function.rs b/codegen/src/test/function.rs index bca0dfdf..04d693b2 100644 --- a/codegen/src/test/function.rs +++ b/codegen/src/test/function.rs @@ -126,7 +126,7 @@ mod function_tests { let err = syn::parse2::(input_tokens).unwrap_err(); assert_eq!( format!("{}", err), - "this type in this position passes from Rhai by value" + "function parameters other than the first one cannot be passed by reference" ); } @@ -139,7 +139,7 @@ mod function_tests { let err = syn::parse2::(input_tokens).unwrap_err(); assert_eq!( format!("{}", err), - "this type in this position passes from Rhai by value" + "function parameters other than the first one cannot be passed by reference" ); } @@ -486,7 +486,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); diff --git a/codegen/src/test/module.rs b/codegen/src/test/module.rs index abcdc0cc..3ada9401 100644 --- a/codegen/src/test/module.rs +++ b/codegen/src/test/module.rs @@ -1096,7 +1096,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) @@ -1155,7 +1155,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) @@ -1235,7 +1235,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(increment(arg0))) @@ -1316,7 +1316,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0))) @@ -1376,7 +1376,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg0 = &mut args[0usize].write_lock::().unwrap(); Ok(Dynamic::from(int_foo(arg0))) @@ -1433,7 +1433,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); @@ -1494,7 +1494,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); @@ -1552,7 +1552,73 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); + } + let arg1 = mem::take(args[1usize]).cast::(); + let arg0 = &mut args[0usize].write_lock::().unwrap(); + Ok(Dynamic::from(get_by_index(arg0, arg1))) + } + + #[inline(always)] fn is_method_call(&self) -> bool { true } + } + } + }; + + let item_mod = syn::parse2::(input_tokens).unwrap(); + assert_streams_eq(item_mod.generate(), expected_tokens); + } + + #[test] + fn one_index_getter_fn_with_cfg_attr_module() { + let input_tokens: TokenStream = quote! { + pub mod one_index_fn { + #[cfg(hello)] + #[rhai_fn(index_get)] + #[some_other_attr] + pub fn get_by_index(x: &mut MyCollection, i: u64) -> FLOAT { + x.get(i) + } + } + }; + + let expected_tokens = quote! { + pub mod one_index_fn { + #[cfg(hello)] + #[some_other_attr] + pub fn get_by_index(x: &mut MyCollection, i: u64) -> FLOAT { + x.get(i) + } + #[allow(unused_imports)] + use super::*; + + pub fn rhai_module_generate() -> Module { + let mut m = Module::new(); + rhai_generate_into_module(&mut m, false); + m.build_index(); + m + } + #[allow(unused_mut)] + pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { + #[cfg(hello)] + m.set_fn("index$get$", FnNamespace::Global, FnAccess::Public, Some(get_by_index_token::PARAM_NAMES), + &[TypeId::of::(), TypeId::of::()], + get_by_index_token().into()); + if flatten {} else {} + } + #[cfg(hello)] + #[allow(non_camel_case_types)] + pub struct get_by_index_token(); + #[cfg(hello)] + impl get_by_index_token { + pub const PARAM_NAMES: &'static [&'static str] = &["x: &mut MyCollection", "i: u64", "FLOAT"]; + #[inline(always)] pub fn param_types() -> [TypeId; 2usize] { [TypeId::of::(), TypeId::of::()] } + } + #[cfg(hello)] + impl PluginFunction for get_by_index_token { + #[inline(always)] + fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { + if args[0usize].is_read_only() { + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); @@ -1613,7 +1679,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg1 = mem::take(args[1usize]).cast::(); let arg0 = &mut args[0usize].write_lock::().unwrap(); @@ -1671,7 +1737,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg1 = mem::take(args[1usize]).cast::(); let arg2 = mem::take(args[2usize]).cast::(); @@ -1733,7 +1799,7 @@ mod generate_tests { #[inline(always)] fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> RhaiResult { if args[0usize].is_read_only() { - return EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE).into()); } let arg1 = mem::take(args[1usize]).cast::(); let arg2 = mem::take(args[2usize]).cast::(); @@ -1811,6 +1877,7 @@ mod generate_tests { pub const MYSTIC_NUMBER: INT = 42; } pub mod second_is { + #[cfg(hello)] pub const SPECIAL_CPU_NUMBER: INT = 68000; } } @@ -1836,6 +1903,7 @@ mod generate_tests { } } pub mod second_is { + #[cfg(hello)] pub const SPECIAL_CPU_NUMBER: INT = 68000; #[allow(unused_imports)] use super::*; @@ -1848,6 +1916,7 @@ mod generate_tests { } #[allow(unused_mut)] pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) { + #[cfg(hello)] m.set_var("SPECIAL_CPU_NUMBER", SPECIAL_CPU_NUMBER); if flatten {} else {} } diff --git a/codegen/ui_tests/export_fn_bad_attr.stderr b/codegen/ui_tests/export_fn_bad_attr.stderr index 12dd2a82..dadd08ea 100644 --- a/codegen/ui_tests/export_fn_bad_attr.stderr +++ b/codegen/ui_tests/export_fn_bad_attr.stderr @@ -1,11 +1,11 @@ error: unknown attribute 'unknown' - --> $DIR/export_fn_bad_attr.rs:9:13 + --> ui_tests/export_fn_bad_attr.rs:9:13 | 9 | #[export_fn(unknown = "thing")] | ^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_bad_attr.rs:19:8 + --> ui_tests/export_fn_bad_attr.rs:19:8 | 19 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_bad_value.stderr b/codegen/ui_tests/export_fn_bad_value.stderr index 4695abb0..08061ff7 100644 --- a/codegen/ui_tests/export_fn_bad_value.stderr +++ b/codegen/ui_tests/export_fn_bad_value.stderr @@ -1,11 +1,11 @@ error: expecting string literal - --> $DIR/export_fn_bad_value.rs:9:20 + --> ui_tests/export_fn_bad_value.rs:9:20 | 9 | #[export_fn(name = true)] | ^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_bad_value.rs:19:8 + --> ui_tests/export_fn_bad_value.rs:19:8 | 19 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_cfg.stderr b/codegen/ui_tests/export_fn_cfg.stderr index ac068be8..049a6224 100644 --- a/codegen/ui_tests/export_fn_cfg.stderr +++ b/codegen/ui_tests/export_fn_cfg.stderr @@ -1,11 +1,11 @@ -error: cfg attributes not allowed on this item - --> $DIR/export_fn_cfg.rs:9:1 +error: `cfg` attributes are not allowed for `export_fn` + --> ui_tests/export_fn_cfg.rs:9:1 | 9 | #[cfg(not(feature = "foo"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_cfg.rs:20:8 + --> ui_tests/export_fn_cfg.rs:20:8 | 20 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_extra_value.stderr b/codegen/ui_tests/export_fn_extra_value.stderr index 6ebc2763..e526aa36 100644 --- a/codegen/ui_tests/export_fn_extra_value.stderr +++ b/codegen/ui_tests/export_fn_extra_value.stderr @@ -1,11 +1,11 @@ error: extraneous value - --> $DIR/export_fn_extra_value.rs:9:26 + --> ui_tests/export_fn_extra_value.rs:9:26 | 9 | #[export_fn(return_raw = "yes")] | ^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_extra_value.rs:19:8 + --> ui_tests/export_fn_extra_value.rs:19:8 | 19 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_junk_arg.stderr b/codegen/ui_tests/export_fn_junk_arg.stderr index 04cf996b..048d95ec 100644 --- a/codegen/ui_tests/export_fn_junk_arg.stderr +++ b/codegen/ui_tests/export_fn_junk_arg.stderr @@ -1,11 +1,11 @@ error: expecting identifier - --> $DIR/export_fn_junk_arg.rs:9:13 + --> ui_tests/export_fn_junk_arg.rs:9:13 | 9 | #[export_fn("wheeeee")] | ^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_junk_arg.rs:19:8 + --> ui_tests/export_fn_junk_arg.rs:19:8 | 19 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_missing_value.stderr b/codegen/ui_tests/export_fn_missing_value.stderr index 978798e5..c34a6a4b 100644 --- a/codegen/ui_tests/export_fn_missing_value.stderr +++ b/codegen/ui_tests/export_fn_missing_value.stderr @@ -1,11 +1,11 @@ error: requires value - --> $DIR/export_fn_missing_value.rs:9:13 + --> ui_tests/export_fn_missing_value.rs:9:13 | 9 | #[export_fn(name)] | ^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_missing_value.rs:19:8 + --> ui_tests/export_fn_missing_value.rs:19:8 | 19 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_path_attr.stderr b/codegen/ui_tests/export_fn_path_attr.stderr index baf499cb..b9d5ec7d 100644 --- a/codegen/ui_tests/export_fn_path_attr.stderr +++ b/codegen/ui_tests/export_fn_path_attr.stderr @@ -1,11 +1,11 @@ error: expecting attribute name - --> $DIR/export_fn_path_attr.rs:9:13 + --> ui_tests/export_fn_path_attr.rs:9:13 | 9 | #[export_fn(rhai::name = "thing")] | ^^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_path_attr.rs:19:8 + --> ui_tests/export_fn_path_attr.rs:19:8 | 19 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_raw_noreturn.stderr b/codegen/ui_tests/export_fn_raw_noreturn.stderr index 51df546a..28744c61 100644 --- a/codegen/ui_tests/export_fn_raw_noreturn.stderr +++ b/codegen/ui_tests/export_fn_raw_noreturn.stderr @@ -1,11 +1,11 @@ error: functions marked with 'return_raw' must return Result> - --> $DIR/export_fn_raw_noreturn.rs:9:13 + --> ui_tests/export_fn_raw_noreturn.rs:9:13 | 9 | #[export_fn(return_raw)] | ^^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/export_fn_raw_noreturn.rs:19:5 + --> ui_tests/export_fn_raw_noreturn.rs:19:5 | 19 | test_fn(&mut n); | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/export_fn_raw_return.stderr b/codegen/ui_tests/export_fn_raw_return.stderr index 3dc04fa8..094b6756 100644 --- a/codegen/ui_tests/export_fn_raw_return.stderr +++ b/codegen/ui_tests/export_fn_raw_return.stderr @@ -1,5 +1,5 @@ error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied - --> $DIR/export_fn_raw_return.rs:10:33 + --> ui_tests/export_fn_raw_return.rs:10:33 | 10 | pub fn test_fn(input: Point) -> bool { | ^^^^ method cannot be called on `bool` due to unsatisfied trait bounds diff --git a/codegen/ui_tests/export_mod_bad_attr.stderr b/codegen/ui_tests/export_mod_bad_attr.stderr index c9318637..bb5b9d11 100644 --- a/codegen/ui_tests/export_mod_bad_attr.stderr +++ b/codegen/ui_tests/export_mod_bad_attr.stderr @@ -1,11 +1,11 @@ error: unknown attribute 'unknown' - --> $DIR/export_mod_bad_attr.rs:11:11 + --> ui_tests/export_mod_bad_attr.rs:11:11 | 11 | #[rhai_fn(unknown = "thing")] | ^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_bad_attr.rs:22:8 + --> ui_tests/export_mod_bad_attr.rs:22:8 | 22 | if test_mod::test_fn(n) { | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_bad_value.stderr b/codegen/ui_tests/export_mod_bad_value.stderr index 683e689d..a5577315 100644 --- a/codegen/ui_tests/export_mod_bad_value.stderr +++ b/codegen/ui_tests/export_mod_bad_value.stderr @@ -1,11 +1,11 @@ error: expecting string literal - --> $DIR/export_mod_bad_value.rs:11:18 + --> ui_tests/export_mod_bad_value.rs:11:18 | 11 | #[rhai_fn(name = true)] | ^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_bad_value.rs:22:8 + --> ui_tests/export_mod_bad_value.rs:22:8 | 22 | if test_mod::test_fn(n) { | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_cfg.stderr b/codegen/ui_tests/export_mod_cfg.stderr index a5b9c027..dc0145f0 100644 --- a/codegen/ui_tests/export_mod_cfg.stderr +++ b/codegen/ui_tests/export_mod_cfg.stderr @@ -1,11 +1,11 @@ -error: cfg attributes not allowed on this item - --> $DIR/export_mod_cfg.rs:11:1 +error: expected attribute arguments in parentheses: #[rhai_fn(...)] + --> ui_tests/export_mod_cfg.rs:12:1 | -11 | #[cfg(not(feature = "foo"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +12 | #[rhai_fn] + | ^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_cfg.rs:23:8 + --> ui_tests/export_mod_cfg.rs:23:8 | 23 | if test_mod::test_fn(n) { | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_extra_value.stderr b/codegen/ui_tests/export_mod_extra_value.stderr index 9ad71395..e1f27073 100644 --- a/codegen/ui_tests/export_mod_extra_value.stderr +++ b/codegen/ui_tests/export_mod_extra_value.stderr @@ -1,11 +1,11 @@ error: extraneous value - --> $DIR/export_mod_extra_value.rs:11:24 + --> ui_tests/export_mod_extra_value.rs:11:24 | 11 | #[rhai_fn(return_raw = "yes")] | ^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_extra_value.rs:22:8 + --> ui_tests/export_mod_extra_value.rs:22:8 | 22 | if test_mod::test_fn(n) { | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_junk_arg.stderr b/codegen/ui_tests/export_mod_junk_arg.stderr index 8d0a9ef9..763f3e73 100644 --- a/codegen/ui_tests/export_mod_junk_arg.stderr +++ b/codegen/ui_tests/export_mod_junk_arg.stderr @@ -1,11 +1,11 @@ error: expecting identifier - --> $DIR/export_mod_junk_arg.rs:11:11 + --> ui_tests/export_mod_junk_arg.rs:11:11 | 11 | #[rhai_fn("wheeeee")] | ^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_junk_arg.rs:22:8 + --> ui_tests/export_mod_junk_arg.rs:22:8 | 22 | if test_mod::test_fn(n) { | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_missing_value.stderr b/codegen/ui_tests/export_mod_missing_value.stderr index b4819fce..fc997c70 100644 --- a/codegen/ui_tests/export_mod_missing_value.stderr +++ b/codegen/ui_tests/export_mod_missing_value.stderr @@ -1,11 +1,11 @@ error: requires value - --> $DIR/export_mod_missing_value.rs:11:11 + --> ui_tests/export_mod_missing_value.rs:11:11 | 11 | #[rhai_fn(name)] | ^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_missing_value.rs:22:8 + --> ui_tests/export_mod_missing_value.rs:22:8 | 22 | if test_mod::test_fn(n) { | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_path_attr.stderr b/codegen/ui_tests/export_mod_path_attr.stderr index 55ca0b2c..2e0f95cb 100644 --- a/codegen/ui_tests/export_mod_path_attr.stderr +++ b/codegen/ui_tests/export_mod_path_attr.stderr @@ -1,11 +1,11 @@ error: expecting attribute name - --> $DIR/export_mod_path_attr.rs:11:11 + --> ui_tests/export_mod_path_attr.rs:11:11 | 11 | #[rhai_fn(rhai::name = "thing")] | ^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_path_attr.rs:22:8 + --> ui_tests/export_mod_path_attr.rs:22:8 | 22 | if test_mod::test_fn(n) { | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_raw_noreturn.stderr b/codegen/ui_tests/export_mod_raw_noreturn.stderr index 71945f4a..ef57fb5c 100644 --- a/codegen/ui_tests/export_mod_raw_noreturn.stderr +++ b/codegen/ui_tests/export_mod_raw_noreturn.stderr @@ -1,11 +1,11 @@ error: functions marked with 'return_raw' must return Result> - --> $DIR/export_mod_raw_noreturn.rs:11:11 + --> ui_tests/export_mod_raw_noreturn.rs:11:11 | 11 | #[rhai_fn(return_raw)] | ^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` - --> $DIR/export_mod_raw_noreturn.rs:22:5 + --> ui_tests/export_mod_raw_noreturn.rs:22:5 | 22 | test_mod::test_fn(&mut n); | ^^^^^^^^ use of undeclared crate or module `test_mod` diff --git a/codegen/ui_tests/export_mod_raw_return.stderr b/codegen/ui_tests/export_mod_raw_return.stderr index d62b9d94..93ad1364 100644 --- a/codegen/ui_tests/export_mod_raw_return.stderr +++ b/codegen/ui_tests/export_mod_raw_return.stderr @@ -1,5 +1,5 @@ error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied - --> $DIR/export_mod_raw_return.rs:12:33 + --> ui_tests/export_mod_raw_return.rs:12:33 | 12 | pub fn test_fn(input: Point) -> bool { | ^^^^ method cannot be called on `bool` due to unsatisfied trait bounds diff --git a/codegen/ui_tests/first_shared_ref.stderr b/codegen/ui_tests/first_shared_ref.stderr index 41b0085e..d82cd9f6 100644 --- a/codegen/ui_tests/first_shared_ref.stderr +++ b/codegen/ui_tests/first_shared_ref.stderr @@ -1,11 +1,11 @@ error: references from Rhai in this position must be mutable - --> $DIR/first_shared_ref.rs:11:23 + --> ui_tests/first_shared_ref.rs:11:23 | 11 | pub fn test_fn(input: &NonClonable) -> bool { | ^^^^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/first_shared_ref.rs:22:8 + --> ui_tests/first_shared_ref.rs:22:8 | 22 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/module_cfg_const.rs b/codegen/ui_tests/module_cfg_const.rs deleted file mode 100644 index 599f52da..00000000 --- a/codegen/ui_tests/module_cfg_const.rs +++ /dev/null @@ -1,31 +0,0 @@ -use rhai::plugin::*; - -#[derive(Clone)] -pub struct Point { - x: f32, - y: f32, -} - -#[export_module] -pub mod test_module { - use rhai::FLOAT; - - #[cfg(feature = "foo")] - pub const MAGIC: FLOAT = 42.0 as FLOAT; - - pub fn test_fn(input: Point) -> bool { - input.x > input.y - } -} - -fn main() { - let n = Point { - x: 0.0, - y: 10.0, - }; - if test_module::test_fn(n) { - println!("yes"); - } else { - println!("no"); - } -} diff --git a/codegen/ui_tests/module_cfg_const.stderr b/codegen/ui_tests/module_cfg_const.stderr deleted file mode 100644 index 9d3bd14d..00000000 --- a/codegen/ui_tests/module_cfg_const.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: cfg attributes not allowed on this item - --> $DIR/module_cfg_const.rs:13:5 - | -13 | #[cfg(feature = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/module_cfg_const.rs:26:8 - | -26 | if test_module::test_fn(n) { - | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/module_cfg_fn.rs b/codegen/ui_tests/module_cfg_fn.rs deleted file mode 100644 index 3613b9a5..00000000 --- a/codegen/ui_tests/module_cfg_fn.rs +++ /dev/null @@ -1,27 +0,0 @@ -use rhai::plugin::*; - -#[derive(Clone)] -pub struct Point { - x: f32, - y: f32, -} - -#[export_module] -pub mod test_module { - #[cfg(not(feature = "foo"))] - pub fn test_fn(input: Point) -> bool { - input.x > input.y - } -} - -fn main() { - let n = Point { - x: 0.0, - y: 10.0, - }; - if test_module::test_fn(n) { - println!("yes"); - } else { - println!("no"); - } -} diff --git a/codegen/ui_tests/module_cfg_fn.stderr b/codegen/ui_tests/module_cfg_fn.stderr deleted file mode 100644 index f2529cbd..00000000 --- a/codegen/ui_tests/module_cfg_fn.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: cfg attributes not allowed on this item - --> $DIR/module_cfg_fn.rs:11:5 - | -11 | #[cfg(not(feature = "foo"))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/module_cfg_fn.rs:22:8 - | -22 | if test_module::test_fn(n) { - | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/non_clonable.stderr b/codegen/ui_tests/non_clonable.stderr index 10a06303..8874257c 100644 --- a/codegen/ui_tests/non_clonable.stderr +++ b/codegen/ui_tests/non_clonable.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied - --> $DIR/non_clonable.rs:11:23 + --> ui_tests/non_clonable.rs:11:23 | 11 | pub fn test_fn(input: NonClonable) -> bool { | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` diff --git a/codegen/ui_tests/non_clonable_second.stderr b/codegen/ui_tests/non_clonable_second.stderr index 07034875..e9d4fc80 100644 --- a/codegen/ui_tests/non_clonable_second.stderr +++ b/codegen/ui_tests/non_clonable_second.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied - --> $DIR/non_clonable_second.rs:11:27 + --> ui_tests/non_clonable_second.rs:11:27 | 11 | pub fn test_fn(a: u32, b: NonClonable) -> bool { | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` diff --git a/codegen/ui_tests/return_mut_ref.stderr b/codegen/ui_tests/return_mut_ref.stderr index 6e56c276..f29c92f1 100644 --- a/codegen/ui_tests/return_mut_ref.stderr +++ b/codegen/ui_tests/return_mut_ref.stderr @@ -1,11 +1,11 @@ error: Rhai functions cannot return references - --> $DIR/return_mut_ref.rs:12:38 + --> ui_tests/return_mut_ref.rs:12:38 | 12 | pub fn test_fn(input: &mut Clonable) -> &mut bool { | ^^^^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/return_mut_ref.rs:23:8 + --> ui_tests/return_mut_ref.rs:23:8 | 23 | if test_fn(n) { | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/return_pointer.stderr b/codegen/ui_tests/return_pointer.stderr index 9b771be6..cc596151 100644 --- a/codegen/ui_tests/return_pointer.stderr +++ b/codegen/ui_tests/return_pointer.stderr @@ -1,11 +1,11 @@ error: Rhai functions cannot return pointers - --> $DIR/return_pointer.rs:12:33 + --> ui_tests/return_pointer.rs:12:33 | 12 | pub fn test_fn(input: Clonable) -> *const str { | ^^^^^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/return_pointer.rs:24:19 + --> ui_tests/return_pointer.rs:24:19 | 24 | let ptr = test_fn(n); | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/return_shared_ref.stderr b/codegen/ui_tests/return_shared_ref.stderr index 9b7a91ca..28418a2e 100644 --- a/codegen/ui_tests/return_shared_ref.stderr +++ b/codegen/ui_tests/return_shared_ref.stderr @@ -1,11 +1,11 @@ error: Rhai functions cannot return references - --> $DIR/return_shared_ref.rs:12:33 + --> ui_tests/return_shared_ref.rs:12:33 | 12 | pub fn test_fn(input: Clonable) -> &'static str { | ^^^^^^^^^^^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/return_shared_ref.rs:23:20 + --> ui_tests/return_shared_ref.rs:23:20 | 23 | println!("{}", test_fn(n)); | ^^^^^^^ not found in this scope diff --git a/codegen/ui_tests/rhai_fn_bad_attr.stderr b/codegen/ui_tests/rhai_fn_bad_attr.stderr index 0f7fa449..f2b04abe 100644 --- a/codegen/ui_tests/rhai_fn_bad_attr.stderr +++ b/codegen/ui_tests/rhai_fn_bad_attr.stderr @@ -1,11 +1,11 @@ error: unknown attribute 'unknown' - --> $DIR/rhai_fn_bad_attr.rs:11:11 + --> ui_tests/rhai_fn_bad_attr.rs:11:11 | 11 | #[rhai_fn(unknown = "thing")] | ^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_bad_attr.rs:22:8 + --> ui_tests/rhai_fn_bad_attr.rs:22:8 | 22 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_bad_value.stderr b/codegen/ui_tests/rhai_fn_bad_value.stderr index f899ddad..b9ff43cd 100644 --- a/codegen/ui_tests/rhai_fn_bad_value.stderr +++ b/codegen/ui_tests/rhai_fn_bad_value.stderr @@ -1,11 +1,11 @@ error: expecting string literal - --> $DIR/rhai_fn_bad_value.rs:11:18 + --> ui_tests/rhai_fn_bad_value.rs:11:18 | 11 | #[rhai_fn(name = true)] | ^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_bad_value.rs:22:8 + --> ui_tests/rhai_fn_bad_value.rs:22:8 | 22 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_extra_value.stderr b/codegen/ui_tests/rhai_fn_extra_value.stderr index 44ecfc0c..0e7ed9cf 100644 --- a/codegen/ui_tests/rhai_fn_extra_value.stderr +++ b/codegen/ui_tests/rhai_fn_extra_value.stderr @@ -1,11 +1,11 @@ error: extraneous value - --> $DIR/rhai_fn_extra_value.rs:11:24 + --> ui_tests/rhai_fn_extra_value.rs:11:24 | 11 | #[rhai_fn(return_raw = "yes")] | ^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_extra_value.rs:22:8 + --> ui_tests/rhai_fn_extra_value.rs:22:8 | 22 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_getter_conflict.stderr b/codegen/ui_tests/rhai_fn_getter_conflict.stderr index b1011bc6..9f8bfc7c 100644 --- a/codegen/ui_tests/rhai_fn_getter_conflict.stderr +++ b/codegen/ui_tests/rhai_fn_getter_conflict.stderr @@ -1,11 +1,11 @@ error: conflicting setter - --> $DIR/rhai_fn_getter_conflict.rs:12:42 + --> ui_tests/rhai_fn_getter_conflict.rs:12:42 | 12 | #[rhai_fn(name = "foo", get = "foo", set = "bar")] | ^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_getter_conflict.rs:23:8 + --> ui_tests/rhai_fn_getter_conflict.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_getter_multiple.stderr b/codegen/ui_tests/rhai_fn_getter_multiple.stderr index b37aca65..4debe3fc 100644 --- a/codegen/ui_tests/rhai_fn_getter_multiple.stderr +++ b/codegen/ui_tests/rhai_fn_getter_multiple.stderr @@ -1,11 +1,11 @@ error: conflicting getter - --> $DIR/rhai_fn_getter_multiple.rs:12:42 + --> ui_tests/rhai_fn_getter_multiple.rs:12:42 | 12 | #[rhai_fn(name = "foo", get = "foo", get = "bar")] | ^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_getter_multiple.rs:23:8 + --> ui_tests/rhai_fn_getter_multiple.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_getter_return.stderr b/codegen/ui_tests/rhai_fn_getter_return.stderr index 9dad293b..6ddce29b 100644 --- a/codegen/ui_tests/rhai_fn_getter_return.stderr +++ b/codegen/ui_tests/rhai_fn_getter_return.stderr @@ -1,11 +1,11 @@ error: property getter must return a value - --> $DIR/rhai_fn_getter_return.rs:13:9 + --> ui_tests/rhai_fn_getter_return.rs:13:9 | 13 | pub fn test_fn(input: &mut Point) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_getter_return.rs:23:5 + --> ui_tests/rhai_fn_getter_return.rs:23:5 | 23 | test_module::test_fn(&mut n); | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_getter_signature.stderr b/codegen/ui_tests/rhai_fn_getter_signature.stderr index 0a7742e6..05aa2a6b 100644 --- a/codegen/ui_tests/rhai_fn_getter_signature.stderr +++ b/codegen/ui_tests/rhai_fn_getter_signature.stderr @@ -1,11 +1,11 @@ error: property getter requires exactly 1 parameter - --> $DIR/rhai_fn_getter_signature.rs:13:20 + --> ui_tests/rhai_fn_getter_signature.rs:13:20 | 13 | pub fn test_fn(input: Point, value: bool) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_getter_signature.rs:23:8 + --> ui_tests/rhai_fn_getter_signature.rs:23:8 | 23 | if test_module::test_fn(n, true) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_global_multiple.stderr b/codegen/ui_tests/rhai_fn_global_multiple.stderr index f36c296d..6e4f2f02 100644 --- a/codegen/ui_tests/rhai_fn_global_multiple.stderr +++ b/codegen/ui_tests/rhai_fn_global_multiple.stderr @@ -1,11 +1,11 @@ error: namespace is already set to 'global' - --> $DIR/rhai_fn_global_multiple.rs:12:23 + --> ui_tests/rhai_fn_global_multiple.rs:12:23 | 12 | #[rhai_fn(global, internal)] | ^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_global_multiple.rs:23:8 + --> ui_tests/rhai_fn_global_multiple.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_index_getter_multiple.stderr b/codegen/ui_tests/rhai_fn_index_getter_multiple.stderr index 30cc273d..cadc8abd 100644 --- a/codegen/ui_tests/rhai_fn_index_getter_multiple.stderr +++ b/codegen/ui_tests/rhai_fn_index_getter_multiple.stderr @@ -1,11 +1,11 @@ error: conflicting index_get - --> $DIR/rhai_fn_index_getter_multiple.rs:12:40 + --> ui_tests/rhai_fn_index_getter_multiple.rs:12:40 | 12 | #[rhai_fn(name = "foo", index_get, index_get)] | ^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_index_getter_multiple.rs:23:8 + --> ui_tests/rhai_fn_index_getter_multiple.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_index_getter_return.stderr b/codegen/ui_tests/rhai_fn_index_getter_return.stderr index b8da178e..0010652f 100644 --- a/codegen/ui_tests/rhai_fn_index_getter_return.stderr +++ b/codegen/ui_tests/rhai_fn_index_getter_return.stderr @@ -1,11 +1,11 @@ error: index getter must return a value - --> $DIR/rhai_fn_index_getter_return.rs:13:9 + --> ui_tests/rhai_fn_index_getter_return.rs:13:9 | 13 | pub fn test_fn(input: &mut Point, i: f32) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_index_getter_return.rs:23:8 + --> ui_tests/rhai_fn_index_getter_return.rs:23:8 | 23 | if test_module::test_fn(&mut n, 5.0) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_index_getter_signature.stderr b/codegen/ui_tests/rhai_fn_index_getter_signature.stderr index 8d567a97..3bc89d88 100644 --- a/codegen/ui_tests/rhai_fn_index_getter_signature.stderr +++ b/codegen/ui_tests/rhai_fn_index_getter_signature.stderr @@ -1,11 +1,11 @@ error: index getter requires exactly 2 parameters - --> $DIR/rhai_fn_index_getter_signature.rs:13:20 + --> ui_tests/rhai_fn_index_getter_signature.rs:13:20 | 13 | pub fn test_fn(input: Point) -> bool { | ^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_index_getter_signature.rs:23:8 + --> ui_tests/rhai_fn_index_getter_signature.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_index_setter_multiple.stderr b/codegen/ui_tests/rhai_fn_index_setter_multiple.stderr index 1e45346d..b56d3bca 100644 --- a/codegen/ui_tests/rhai_fn_index_setter_multiple.stderr +++ b/codegen/ui_tests/rhai_fn_index_setter_multiple.stderr @@ -1,11 +1,11 @@ error: conflicting index_set - --> $DIR/rhai_fn_index_setter_multiple.rs:12:40 + --> ui_tests/rhai_fn_index_setter_multiple.rs:12:40 | 12 | #[rhai_fn(name = "foo", index_set, index_set)] | ^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_index_setter_multiple.rs:23:8 + --> ui_tests/rhai_fn_index_setter_multiple.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_junk_arg.stderr b/codegen/ui_tests/rhai_fn_junk_arg.stderr index 2fa0be8d..d538eb3f 100644 --- a/codegen/ui_tests/rhai_fn_junk_arg.stderr +++ b/codegen/ui_tests/rhai_fn_junk_arg.stderr @@ -1,11 +1,11 @@ error: expecting identifier - --> $DIR/rhai_fn_junk_arg.rs:11:11 + --> ui_tests/rhai_fn_junk_arg.rs:11:11 | 11 | #[rhai_fn("wheeeee")] | ^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_junk_arg.rs:22:8 + --> ui_tests/rhai_fn_junk_arg.rs:22:8 | 22 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_missing_value.stderr b/codegen/ui_tests/rhai_fn_missing_value.stderr index 1cd4b241..bba6952a 100644 --- a/codegen/ui_tests/rhai_fn_missing_value.stderr +++ b/codegen/ui_tests/rhai_fn_missing_value.stderr @@ -1,11 +1,11 @@ error: requires value - --> $DIR/rhai_fn_missing_value.rs:11:11 + --> ui_tests/rhai_fn_missing_value.rs:11:11 | 11 | #[rhai_fn(name)] | ^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_missing_value.rs:22:8 + --> ui_tests/rhai_fn_missing_value.rs:22:8 | 22 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_non_clonable_return.stderr b/codegen/ui_tests/rhai_fn_non_clonable_return.stderr index 70d877e8..c8ee6dc5 100644 --- a/codegen/ui_tests/rhai_fn_non_clonable_return.stderr +++ b/codegen/ui_tests/rhai_fn_non_clonable_return.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied - --> $DIR/rhai_fn_non_clonable_return.rs:11:8 + --> ui_tests/rhai_fn_non_clonable_return.rs:11:8 | 11 | pub fn test_fn(input: f32) -> NonClonable { | ^^^^^^^^^^^^^^^^^^^^^^^----------- @@ -8,7 +8,7 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied | the trait `Clone` is not implemented for `NonClonable` | note: required by a bound in `rhai::Dynamic::from` - --> $DIR/dynamic.rs:1122:30 + --> $WORKSPACE/src/dynamic.rs | -1122 | pub fn from(mut value: T) -> Self { + | pub fn from(mut value: T) -> Self { | ^^^^^ required by this bound in `rhai::Dynamic::from` diff --git a/codegen/ui_tests/rhai_fn_path_attr.stderr b/codegen/ui_tests/rhai_fn_path_attr.stderr index 70c3b155..0a25e87d 100644 --- a/codegen/ui_tests/rhai_fn_path_attr.stderr +++ b/codegen/ui_tests/rhai_fn_path_attr.stderr @@ -1,11 +1,11 @@ error: expecting attribute name - --> $DIR/rhai_fn_path_attr.rs:11:11 + --> ui_tests/rhai_fn_path_attr.rs:11:11 | 11 | #[rhai_fn(rhai::name = "thing")] | ^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_path_attr.rs:22:8 + --> ui_tests/rhai_fn_path_attr.rs:22:8 | 22 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_collision.stderr b/codegen/ui_tests/rhai_fn_rename_collision.stderr index fcbecd8a..758e25a0 100644 --- a/codegen/ui_tests/rhai_fn_rename_collision.stderr +++ b/codegen/ui_tests/rhai_fn_rename_collision.stderr @@ -1,17 +1,17 @@ error: duplicate Rhai signature for 'foo' - --> $DIR/rhai_fn_rename_collision.rs:17:15 + --> ui_tests/rhai_fn_rename_collision.rs:17:15 | 17 | #[rhai_fn(name = "foo")] | ^^^^^^^^^^^^ error: duplicated function renamed 'foo' - --> $DIR/rhai_fn_rename_collision.rs:12:15 + --> ui_tests/rhai_fn_rename_collision.rs:12:15 | 12 | #[rhai_fn(name = "foo")] | ^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_collision.rs:28:8 + --> ui_tests/rhai_fn_rename_collision.rs:28:8 | 28 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_collision_oneattr.stderr b/codegen/ui_tests/rhai_fn_rename_collision_oneattr.stderr index fc5170a6..ff7d8cc7 100644 --- a/codegen/ui_tests/rhai_fn_rename_collision_oneattr.stderr +++ b/codegen/ui_tests/rhai_fn_rename_collision_oneattr.stderr @@ -1,17 +1,17 @@ error: duplicate Rhai signature for 'foo' - --> $DIR/rhai_fn_rename_collision_oneattr.rs:17:12 + --> ui_tests/rhai_fn_rename_collision_oneattr.rs:17:12 | 17 | pub fn foo(input: Point) -> bool { | ^^^ error: duplicated function 'foo' - --> $DIR/rhai_fn_rename_collision_oneattr.rs:12:15 + --> ui_tests/rhai_fn_rename_collision_oneattr.rs:12:15 | 12 | #[rhai_fn(name = "foo")] | ^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_collision_oneattr.rs:27:8 + --> ui_tests/rhai_fn_rename_collision_oneattr.rs:27:8 | 27 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_collision_oneattr_multiple.stderr b/codegen/ui_tests/rhai_fn_rename_collision_oneattr_multiple.stderr index 67b9eef5..b36aee76 100644 --- a/codegen/ui_tests/rhai_fn_rename_collision_oneattr_multiple.stderr +++ b/codegen/ui_tests/rhai_fn_rename_collision_oneattr_multiple.stderr @@ -1,17 +1,17 @@ error: duplicate Rhai signature for 'bar' - --> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:17:15 + --> ui_tests/rhai_fn_rename_collision_oneattr_multiple.rs:17:15 | 17 | #[rhai_fn(get = "bar")] | ^^^^^^^^^^^ error: duplicated function renamed 'bar' - --> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:12:15 + --> ui_tests/rhai_fn_rename_collision_oneattr_multiple.rs:12:15 | 12 | #[rhai_fn(name = "foo", get = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_collision_oneattr_multiple.rs:25:8 + --> ui_tests/rhai_fn_rename_collision_oneattr_multiple.rs:25:8 | 25 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_collision_with_itself.stderr b/codegen/ui_tests/rhai_fn_rename_collision_with_itself.stderr index 5e27be60..430fd104 100644 --- a/codegen/ui_tests/rhai_fn_rename_collision_with_itself.stderr +++ b/codegen/ui_tests/rhai_fn_rename_collision_with_itself.stderr @@ -1,17 +1,17 @@ error: duplicate Rhai signature for 'foo' - --> $DIR/rhai_fn_rename_collision_with_itself.rs:12:15 + --> ui_tests/rhai_fn_rename_collision_with_itself.rs:12:15 | 12 | #[rhai_fn(name = "foo", name = "bar", name = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: duplicated function renamed 'foo' - --> $DIR/rhai_fn_rename_collision_with_itself.rs:12:15 + --> ui_tests/rhai_fn_rename_collision_with_itself.rs:12:15 | 12 | #[rhai_fn(name = "foo", name = "bar", name = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_collision_with_itself.rs:20:8 + --> ui_tests/rhai_fn_rename_collision_with_itself.rs:20:8 | 20 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_to_index_getter.stderr b/codegen/ui_tests/rhai_fn_rename_to_index_getter.stderr index 64c11d92..c702d3f0 100644 --- a/codegen/ui_tests/rhai_fn_rename_to_index_getter.stderr +++ b/codegen/ui_tests/rhai_fn_rename_to_index_getter.stderr @@ -1,11 +1,11 @@ error: use attribute 'index_get' instead - --> $DIR/rhai_fn_rename_to_index_getter.rs:12:15 + --> ui_tests/rhai_fn_rename_to_index_getter.rs:12:15 | 12 | #[rhai_fn(name = "index$get$")] | ^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_to_index_getter.rs:23:8 + --> ui_tests/rhai_fn_rename_to_index_getter.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_to_index_setter.stderr b/codegen/ui_tests/rhai_fn_rename_to_index_setter.stderr index 0d9c9f3d..ee176580 100644 --- a/codegen/ui_tests/rhai_fn_rename_to_index_setter.stderr +++ b/codegen/ui_tests/rhai_fn_rename_to_index_setter.stderr @@ -1,11 +1,11 @@ error: use attribute 'index_set' instead - --> $DIR/rhai_fn_rename_to_index_setter.rs:12:15 + --> ui_tests/rhai_fn_rename_to_index_setter.rs:12:15 | 12 | #[rhai_fn(name = "index$set$")] | ^^^^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_to_index_setter.rs:23:8 + --> ui_tests/rhai_fn_rename_to_index_setter.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_to_prop_getter.stderr b/codegen/ui_tests/rhai_fn_rename_to_prop_getter.stderr index cee9c66b..7e3645ff 100644 --- a/codegen/ui_tests/rhai_fn_rename_to_prop_getter.stderr +++ b/codegen/ui_tests/rhai_fn_rename_to_prop_getter.stderr @@ -1,11 +1,11 @@ error: use attribute 'getter = "foo"' instead - --> $DIR/rhai_fn_rename_to_prop_getter.rs:12:15 + --> ui_tests/rhai_fn_rename_to_prop_getter.rs:12:15 | 12 | #[rhai_fn(name = "get$foo")] | ^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_to_prop_getter.rs:23:8 + --> ui_tests/rhai_fn_rename_to_prop_getter.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_rename_to_prop_setter.stderr b/codegen/ui_tests/rhai_fn_rename_to_prop_setter.stderr index 9544ce93..86a0743a 100644 --- a/codegen/ui_tests/rhai_fn_rename_to_prop_setter.stderr +++ b/codegen/ui_tests/rhai_fn_rename_to_prop_setter.stderr @@ -1,11 +1,11 @@ error: use attribute 'getter = "foo"' instead - --> $DIR/rhai_fn_rename_to_prop_setter.rs:12:15 + --> ui_tests/rhai_fn_rename_to_prop_setter.rs:12:15 | 12 | #[rhai_fn(name = "get$foo")] | ^^^^^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_rename_to_prop_setter.rs:23:8 + --> ui_tests/rhai_fn_rename_to_prop_setter.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_setter_index_signature.stderr b/codegen/ui_tests/rhai_fn_setter_index_signature.stderr index aa9548e1..ac8344b3 100644 --- a/codegen/ui_tests/rhai_fn_setter_index_signature.stderr +++ b/codegen/ui_tests/rhai_fn_setter_index_signature.stderr @@ -1,11 +1,11 @@ error: index setter requires exactly 3 parameters - --> $DIR/rhai_fn_setter_index_signature.rs:13:20 + --> ui_tests/rhai_fn_setter_index_signature.rs:13:20 | 13 | pub fn test_fn(input: Point) -> bool { | ^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_setter_index_signature.rs:23:8 + --> ui_tests/rhai_fn_setter_index_signature.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_setter_multiple.stderr b/codegen/ui_tests/rhai_fn_setter_multiple.stderr index 6783fb1a..a13f7685 100644 --- a/codegen/ui_tests/rhai_fn_setter_multiple.stderr +++ b/codegen/ui_tests/rhai_fn_setter_multiple.stderr @@ -1,11 +1,11 @@ error: conflicting setter - --> $DIR/rhai_fn_setter_multiple.rs:12:42 + --> ui_tests/rhai_fn_setter_multiple.rs:12:42 | 12 | #[rhai_fn(name = "foo", set = "foo", set = "bar")] | ^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_setter_multiple.rs:23:8 + --> ui_tests/rhai_fn_setter_multiple.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_setter_return.stderr b/codegen/ui_tests/rhai_fn_setter_return.stderr index 8c0b21ab..6d534c92 100644 --- a/codegen/ui_tests/rhai_fn_setter_return.stderr +++ b/codegen/ui_tests/rhai_fn_setter_return.stderr @@ -1,11 +1,11 @@ error: property setter cannot return any value - --> $DIR/rhai_fn_setter_return.rs:13:51 + --> ui_tests/rhai_fn_setter_return.rs:13:51 | 13 | pub fn test_fn(input: &mut Point, value: f32) -> bool { | ^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_setter_return.rs:24:8 + --> ui_tests/rhai_fn_setter_return.rs:24:8 | 24 | if test_module::test_fn(&mut n, 5.0) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_fn_setter_signature.stderr b/codegen/ui_tests/rhai_fn_setter_signature.stderr index d5f3c9d3..87cb8d0c 100644 --- a/codegen/ui_tests/rhai_fn_setter_signature.stderr +++ b/codegen/ui_tests/rhai_fn_setter_signature.stderr @@ -1,11 +1,11 @@ error: property setter requires exactly 2 parameters - --> $DIR/rhai_fn_setter_signature.rs:13:20 + --> ui_tests/rhai_fn_setter_signature.rs:13:20 | 13 | pub fn test_fn(input: Point) -> bool { | ^^^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_fn_setter_signature.rs:23:8 + --> ui_tests/rhai_fn_setter_signature.rs:23:8 | 23 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_bad_attr.stderr b/codegen/ui_tests/rhai_mod_bad_attr.stderr index 8ac71f6c..8bc7c037 100644 --- a/codegen/ui_tests/rhai_mod_bad_attr.stderr +++ b/codegen/ui_tests/rhai_mod_bad_attr.stderr @@ -1,11 +1,11 @@ error: unknown attribute 'unknown' - --> $DIR/rhai_mod_bad_attr.rs:11:12 + --> ui_tests/rhai_mod_bad_attr.rs:11:12 | 11 | #[rhai_mod(unknown = "thing")] | ^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_mod_bad_attr.rs:24:8 + --> ui_tests/rhai_mod_bad_attr.rs:24:8 | 24 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_bad_value.stderr b/codegen/ui_tests/rhai_mod_bad_value.stderr index 76498300..f3110cc6 100644 --- a/codegen/ui_tests/rhai_mod_bad_value.stderr +++ b/codegen/ui_tests/rhai_mod_bad_value.stderr @@ -1,11 +1,11 @@ error: expecting string literal - --> $DIR/rhai_mod_bad_value.rs:11:19 + --> ui_tests/rhai_mod_bad_value.rs:11:19 | 11 | #[rhai_mod(name = true)] | ^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_mod_bad_value.rs:24:8 + --> ui_tests/rhai_mod_bad_value.rs:24:8 | 24 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_inner_cfg_false.stderr b/codegen/ui_tests/rhai_mod_inner_cfg_false.stderr index 04068220..b0feeb47 100644 --- a/codegen/ui_tests/rhai_mod_inner_cfg_false.stderr +++ b/codegen/ui_tests/rhai_mod_inner_cfg_false.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: could not find `test_mod` in `test_module` - --> $DIR/rhai_mod_inner_cfg_false.rs:24:21 + --> ui_tests/rhai_mod_inner_cfg_false.rs:24:21 | 24 | if test_module::test_mod::test_fn(n) { | ^^^^^^^^ could not find `test_mod` in `test_module` diff --git a/codegen/ui_tests/rhai_mod_junk_arg.stderr b/codegen/ui_tests/rhai_mod_junk_arg.stderr index a8c733a0..819b8797 100644 --- a/codegen/ui_tests/rhai_mod_junk_arg.stderr +++ b/codegen/ui_tests/rhai_mod_junk_arg.stderr @@ -1,11 +1,11 @@ error: expecting identifier - --> $DIR/rhai_mod_junk_arg.rs:11:12 + --> ui_tests/rhai_mod_junk_arg.rs:11:12 | 11 | #[rhai_mod("wheeeee")] | ^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_mod_junk_arg.rs:24:8 + --> ui_tests/rhai_mod_junk_arg.rs:24:8 | 24 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_missing_value.stderr b/codegen/ui_tests/rhai_mod_missing_value.stderr index ed452923..0036ae13 100644 --- a/codegen/ui_tests/rhai_mod_missing_value.stderr +++ b/codegen/ui_tests/rhai_mod_missing_value.stderr @@ -1,11 +1,11 @@ error: requires value - --> $DIR/rhai_mod_missing_value.rs:11:12 + --> ui_tests/rhai_mod_missing_value.rs:11:12 | 11 | #[rhai_mod(name)] | ^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_mod_missing_value.rs:24:8 + --> ui_tests/rhai_mod_missing_value.rs:24:8 | 24 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_name_collisions.stderr b/codegen/ui_tests/rhai_mod_name_collisions.stderr index 53c209e1..6b3f1a41 100644 --- a/codegen/ui_tests/rhai_mod_name_collisions.stderr +++ b/codegen/ui_tests/rhai_mod_name_collisions.stderr @@ -1,17 +1,17 @@ error: duplicate function 'test_fn' - --> $DIR/rhai_mod_name_collisions.rs:16:12 + --> ui_tests/rhai_mod_name_collisions.rs:16:12 | 16 | pub fn test_fn(input: Point) -> bool { | ^^^^^^^ error: duplicated function 'test_fn' - --> $DIR/rhai_mod_name_collisions.rs:12:12 + --> ui_tests/rhai_mod_name_collisions.rs:12:12 | 12 | pub fn test_fn(input: Point) -> bool { | ^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_mod_name_collisions.rs:26:8 + --> ui_tests/rhai_mod_name_collisions.rs:26:8 | 26 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_non_clonable_return.stderr b/codegen/ui_tests/rhai_mod_non_clonable_return.stderr index 82e9725b..c835c4b8 100644 --- a/codegen/ui_tests/rhai_mod_non_clonable_return.stderr +++ b/codegen/ui_tests/rhai_mod_non_clonable_return.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied - --> $DIR/rhai_mod_non_clonable_return.rs:12:12 + --> ui_tests/rhai_mod_non_clonable_return.rs:12:12 | 12 | pub fn test_fn(input: f32) -> NonClonable { | ^^^^^^^^^^^^^^^^^^^^^^^----------- @@ -8,7 +8,7 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied | the trait `Clone` is not implemented for `NonClonable` | note: required by a bound in `rhai::Dynamic::from` - --> $DIR/dynamic.rs:1122:30 + --> $WORKSPACE/src/dynamic.rs | -1122 | pub fn from(mut value: T) -> Self { + | pub fn from(mut value: T) -> Self { | ^^^^^ required by this bound in `rhai::Dynamic::from` diff --git a/codegen/ui_tests/rhai_mod_path_attr.stderr b/codegen/ui_tests/rhai_mod_path_attr.stderr index cb99205a..51ac6709 100644 --- a/codegen/ui_tests/rhai_mod_path_attr.stderr +++ b/codegen/ui_tests/rhai_mod_path_attr.stderr @@ -1,11 +1,11 @@ error: expecting attribute name - --> $DIR/rhai_mod_path_attr.rs:11:12 + --> ui_tests/rhai_mod_path_attr.rs:11:12 | 11 | #[rhai_mod(rhai::name = "thing")] | ^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_mod_path_attr.rs:24:8 + --> ui_tests/rhai_mod_path_attr.rs:24:8 | 24 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_return_raw.stderr b/codegen/ui_tests/rhai_mod_return_raw.stderr index 50ab3bef..b3b8443d 100644 --- a/codegen/ui_tests/rhai_mod_return_raw.stderr +++ b/codegen/ui_tests/rhai_mod_return_raw.stderr @@ -1,11 +1,11 @@ error: unknown attribute 'return_raw' - --> $DIR/rhai_mod_return_raw.rs:11:12 + --> ui_tests/rhai_mod_return_raw.rs:11:12 | 11 | #[rhai_mod(return_raw = "yes")] | ^^^^^^^^^^ error[E0433]: failed to resolve: use of undeclared crate or module `test_module` - --> $DIR/rhai_mod_return_raw.rs:24:8 + --> ui_tests/rhai_mod_return_raw.rs:24:8 | 24 | if test_module::test_fn(n) { | ^^^^^^^^^^^ use of undeclared crate or module `test_module` diff --git a/codegen/ui_tests/rhai_mod_unknown_type.stderr b/codegen/ui_tests/rhai_mod_unknown_type.stderr index 5853808f..2a68d792 100644 --- a/codegen/ui_tests/rhai_mod_unknown_type.stderr +++ b/codegen/ui_tests/rhai_mod_unknown_type.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Pointer` in this scope - --> $DIR/rhai_mod_unknown_type.rs:12:27 + --> ui_tests/rhai_mod_unknown_type.rs:12:27 | 4 | pub struct Point { | ---------------- similarly named struct `Point` defined here diff --git a/codegen/ui_tests/rhai_mod_unknown_type_return.stderr b/codegen/ui_tests/rhai_mod_unknown_type_return.stderr index 43f2896c..4a8bf32b 100644 --- a/codegen/ui_tests/rhai_mod_unknown_type_return.stderr +++ b/codegen/ui_tests/rhai_mod_unknown_type_return.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `boool` in this scope - --> $DIR/rhai_mod_unknown_type_return.rs:12:37 + --> ui_tests/rhai_mod_unknown_type_return.rs:12:37 | 12 | pub fn test_fn(input: Point) -> boool { | ^^^^^ help: a builtin type with a similar name exists: `bool` diff --git a/codegen/ui_tests/second_shared_ref.stderr b/codegen/ui_tests/second_shared_ref.stderr index 91b493ed..63f4f9ab 100644 --- a/codegen/ui_tests/second_shared_ref.stderr +++ b/codegen/ui_tests/second_shared_ref.stderr @@ -1,11 +1,11 @@ -error: this type in this position passes from Rhai by value - --> $DIR/second_shared_ref.rs:12:41 +error: function parameters other than the first one cannot be passed by reference + --> ui_tests/second_shared_ref.rs:12:41 | 12 | pub fn test_fn(input: Clonable, factor: &bool) -> bool { | ^^^^^ error[E0425]: cannot find function `test_fn` in this scope - --> $DIR/second_shared_ref.rs:23:8 + --> ui_tests/second_shared_ref.rs:23:8 | 23 | if test_fn(n, &true) { | ^^^^^^^ not found in this scope diff --git a/src/ast.rs b/src/ast.rs index 3e1cd195..3cf2b739 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -718,7 +718,7 @@ impl AST { /// Not available under `no_function`. #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_module"))] - #[inline(always)] + #[inline] pub(crate) fn iter_fn_def(&self) -> impl Iterator { self.functions .iter_script_fn() @@ -728,7 +728,7 @@ impl AST { /// /// Not available under `no_function`. #[cfg(not(feature = "no_function"))] - #[inline(always)] + #[inline] pub fn iter_functions<'a>(&'a self) -> impl Iterator + 'a { self.functions .iter_script_fn() @@ -944,7 +944,7 @@ impl fmt::Debug for StmtBlock { } impl From for Stmt { - #[inline(always)] + #[inline] fn from(block: StmtBlock) -> Self { let block_pos = block.position(); Self::Block(block.0.into_boxed_slice(), block_pos) @@ -1852,7 +1852,7 @@ impl From for FloatWrapper { impl FromStr for FloatWrapper { type Err = ::Err; - #[inline(always)] + #[inline] fn from_str(s: &str) -> Result { F::from_str(s).map(Into::::into) } @@ -2003,14 +2003,12 @@ impl fmt::Debug for Expr { } Self::Variable(i, _, x) => { f.write_str("Variable(")?; - match x.1 { - Some((_, ref namespace)) => write!(f, "{}", namespace)?, - _ => (), + if let Some((_, ref namespace)) = x.1 { + write!(f, "{}", namespace)? } f.write_str(&x.2)?; - match i.map_or_else(|| x.0, |n| NonZeroUsize::new(n.get() as usize)) { - Some(n) => write!(f, " #{}", n)?, - _ => (), + if let Some(n) = i.map_or_else(|| x.0, |n| NonZeroUsize::new(n.get() as usize)) { + write!(f, " #{}", n)? } f.write_str(")") } @@ -2134,7 +2132,7 @@ impl Expr { } } /// Is the expression a simple variable access? - #[inline(always)] + #[inline] #[must_use] pub(crate) const fn is_variable_access(&self, non_qualified: bool) -> bool { match self { @@ -2143,7 +2141,7 @@ impl Expr { } } /// Return the variable name if the expression a simple variable access. - #[inline(always)] + #[inline] #[must_use] pub(crate) fn get_variable_name(&self, non_qualified: bool) -> Option<&str> { match self { diff --git a/src/deprecated.rs b/src/deprecated.rs index 407f9630..e4fa7e67 100644 --- a/src/deprecated.rs +++ b/src/deprecated.rs @@ -1,6 +1,8 @@ //! Module containing all deprecated API that will be removed in the next major version. -use crate::{Dynamic, Engine, EvalAltResult, ImmutableString, Scope, AST}; +use crate::{ + Dynamic, Engine, EvalAltResult, ImmutableString, NativeCallContext, RhaiResult, Scope, AST, +}; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -141,3 +143,37 @@ impl Dynamic { self.into_immutable_string() } } + +impl NativeCallContext<'_> { + /// Call a function inside the call context. + /// + /// # WARNING + /// + /// All arguments may be _consumed_, meaning that they may be replaced by `()`. + /// This is to avoid unnecessarily cloning the arguments. + /// + /// Do not use the arguments after this call. If they are needed afterwards, + /// clone them _before_ calling this function. + /// + /// If `is_method` is [`true`], the first argument is assumed to be passed + /// by reference and is not consumed. + #[deprecated(since = "1.2.0", note = "use `call_fn_raw` instead")] + #[inline(always)] + pub fn call_fn_dynamic_raw( + &self, + fn_name: impl AsRef, + is_method_call: bool, + args: &mut [&mut Dynamic], + ) -> RhaiResult { + self.call_fn_raw(fn_name.as_ref(), is_method_call, is_method_call, args) + } +} + +#[allow(useless_deprecated)] +#[deprecated(since = "1.2.0", note = "explicitly wrap `EvalAltResult` in `Err`")] +impl From for Result> { + #[inline(always)] + fn from(err: EvalAltResult) -> Self { + Err(err.into()) + } +} diff --git a/src/dynamic.rs b/src/dynamic.rs index ae2096ab..76d99ad9 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -255,7 +255,7 @@ enum DynamicReadLockInner<'d, T: Clone> { impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> { type Target = T; - #[inline(always)] + #[inline] fn deref(&self) -> &Self::Target { match self.0 { DynamicReadLockInner::Reference(ref reference) => *reference, @@ -296,7 +296,7 @@ enum DynamicWriteLockInner<'d, T: Clone> { impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> { type Target = T; - #[inline(always)] + #[inline] fn deref(&self) -> &Self::Target { match self.0 { DynamicWriteLockInner::Reference(ref reference) => *reference, @@ -307,7 +307,7 @@ impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> { } impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> { - #[inline(always)] + #[inline] fn deref_mut(&mut self) -> &mut Self::Target { match self.0 { DynamicWriteLockInner::Reference(ref mut reference) => *reference, @@ -384,17 +384,16 @@ impl Dynamic { #[inline(always)] #[must_use] pub const fn is_shared(&self) -> bool { - match self.0 { - #[cfg(not(feature = "no_closure"))] - Union::Shared(_, _, _) => true, - _ => false, - } + #[cfg(not(feature = "no_closure"))] + return matches!(self.0, Union::Shared(_, _, _)); + #[cfg(feature = "no_closure")] + return false; } /// Is the value held by this [`Dynamic`] a particular type? /// /// If the [`Dynamic`] is a shared variant checking is performed on /// top of its internal value. - #[inline(always)] + #[inline] #[must_use] pub fn is(&self) -> bool { if TypeId::of::() == TypeId::of::() { @@ -1221,7 +1220,7 @@ impl Dynamic { /// /// If the [`Dynamic`] value is already shared, this method returns itself. #[cfg(not(feature = "no_closure"))] - #[inline(always)] + #[inline] #[must_use] pub fn into_shared(self) -> Self { let _access = self.access_mode(); @@ -1452,7 +1451,7 @@ impl Dynamic { /// If the [`Dynamic`] is not a shared value, it returns a cloned copy. /// /// If the [`Dynamic`] is a shared value, it returns a cloned copy of the shared value. - #[inline(always)] + #[inline] #[must_use] pub fn flatten_clone(&self) -> Self { match self.0 { @@ -1471,7 +1470,7 @@ impl Dynamic { /// /// If the [`Dynamic`] is a shared value, it returns the shared value if there are no /// outstanding references, or a cloned copy. - #[inline(always)] + #[inline] #[must_use] pub fn flatten(self) -> Self { match self.0 { @@ -1495,7 +1494,7 @@ impl Dynamic { /// /// If the [`Dynamic`] is a shared value, it is set to the shared value if there are no /// outstanding references, or a cloned copy otherwise. - #[inline(always)] + #[inline] pub(crate) fn flatten_in_place(&mut self) -> &mut Self { match self.0 { #[cfg(not(feature = "no_closure"))] @@ -1528,7 +1527,7 @@ impl Dynamic { /// Access just waits until the [`RwLock`][std::sync::RwLock] is released. /// So this method always returns [`false`] under [`Sync`]. #[cfg(not(feature = "no_closure"))] - #[inline(always)] + #[inline] #[must_use] pub fn is_locked(&self) -> bool { #[cfg(not(feature = "no_closure"))] @@ -1895,7 +1894,7 @@ impl Dynamic { /// Convert the [`Dynamic`] into a [`String`] and return it. /// If there are other references to the same string, a cloned copy is returned. /// Returns the name of the actual type if the cast fails. - #[inline(always)] + #[inline] pub fn into_string(self) -> Result { self.into_immutable_string() .map(ImmutableString::into_owned) @@ -1997,7 +1996,7 @@ impl Dynamic { } #[cfg(not(feature = "no_index"))] impl From> for Dynamic { - #[inline(always)] + #[inline] fn from(value: Vec) -> Self { Self(Union::Array( Box::new(value.into_iter().map(Dynamic::from).collect()), @@ -2008,7 +2007,7 @@ impl From> for Dynamic { } #[cfg(not(feature = "no_index"))] impl From<&[T]> for Dynamic { - #[inline(always)] + #[inline] fn from(value: &[T]) -> Self { Self(Union::Array( Box::new(value.iter().cloned().map(Dynamic::from).collect()), @@ -2019,7 +2018,7 @@ impl From<&[T]> for Dynamic { } #[cfg(not(feature = "no_index"))] impl std::iter::FromIterator for Dynamic { - #[inline(always)] + #[inline] fn from_iter>(iter: X) -> Self { Self(Union::Array( Box::new(iter.into_iter().map(Dynamic::from).collect()), diff --git a/src/engine.rs b/src/engine.rs index 477e3f6e..b5349485 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -9,7 +9,6 @@ use crate::fn_native::{ OnVarCallback, }; use crate::module::NamespaceRef; -use crate::optimize::OptimizationLevel; use crate::packages::{Package, StandardPackage}; use crate::r#unsafe::unsafe_cast_var_name_to_lifetime; use crate::token::Token; @@ -144,7 +143,7 @@ impl Imports { } /// Does the specified function hash key exist in this stack of imported [modules][Module]? #[allow(dead_code)] - #[inline(always)] + #[inline] #[must_use] pub fn contains_fn(&self, hash: u64) -> bool { self.modules.iter().any(|m| m.contains_qualified_fn(hash)) @@ -161,7 +160,7 @@ impl Imports { /// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of /// imported [modules][Module]? #[allow(dead_code)] - #[inline(always)] + #[inline] #[must_use] pub fn contains_iter(&self, id: TypeId) -> bool { self.modules.iter().any(|m| m.contains_qualified_iter(id)) @@ -888,7 +887,7 @@ impl<'x, 'px, 'pt> EvalContext<'_, 'x, 'px, '_, '_, '_, '_, 'pt> { self.mods } /// Get an iterator over the namespaces containing definition of all script-defined functions. - #[inline(always)] + #[inline] pub fn iter_namespaces(&self) -> impl Iterator { self.lib.iter().cloned() } @@ -979,7 +978,8 @@ pub struct Engine { pub(crate) progress: Option, /// Optimize the AST after compilation. - pub(crate) optimization_level: OptimizationLevel, + #[cfg(not(feature = "no_optimize"))] + pub(crate) optimization_level: crate::OptimizationLevel, /// Max limits. #[cfg(not(feature = "unchecked"))] @@ -1101,6 +1101,7 @@ impl Engine { #[cfg(not(feature = "unchecked"))] progress: None, + #[cfg(not(feature = "no_optimize"))] optimization_level: Default::default(), #[cfg(not(feature = "unchecked"))] @@ -1221,7 +1222,7 @@ impl Engine { return if let Some(val) = this_ptr { Ok(((*val).into(), *pos)) } else { - EvalAltResult::ErrorUnboundThis(*pos).into() + Err(EvalAltResult::ErrorUnboundThis(*pos).into()) } } _ if state.always_search_scope => (0, expr.position()), @@ -1723,7 +1724,7 @@ impl Engine { } } // Syntax error - _ => EvalAltResult::ErrorDotExpr("".into(), rhs.position()).into(), + _ => Err(EvalAltResult::ErrorDotExpr("".into(), rhs.position()).into()), } } } @@ -1958,12 +1959,11 @@ impl Engine { arr_len - index .checked_abs() - .ok_or_else(|| { - EvalAltResult::ErrorArrayBounds(arr_len, index, idx_pos).into() - }) + .ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr_len, index, idx_pos)) .and_then(|n| { if n as usize > arr_len { - EvalAltResult::ErrorArrayBounds(arr_len, index, idx_pos).into() + Err(EvalAltResult::ErrorArrayBounds(arr_len, index, idx_pos) + .into()) } else { Ok(n as usize) } @@ -2014,7 +2014,9 @@ impl Engine { let offset = index as usize; ( if offset >= bits { - return EvalAltResult::ErrorBitFieldBounds(bits, index, idx_pos).into(); + return Err( + EvalAltResult::ErrorBitFieldBounds(bits, index, idx_pos).into() + ); } else { (*value & (1 << offset)) != 0 }, @@ -2025,14 +2027,16 @@ impl Engine { ( // Count from end if negative if offset > bits { - return EvalAltResult::ErrorBitFieldBounds(bits, index, idx_pos).into(); + return Err( + EvalAltResult::ErrorBitFieldBounds(bits, index, idx_pos).into() + ); } else { (*value & (1 << (bits - offset))) != 0 }, offset, ) } else { - return EvalAltResult::ErrorBitFieldBounds(bits, index, idx_pos).into(); + return Err(EvalAltResult::ErrorBitFieldBounds(bits, index, idx_pos).into()); }; Ok(Target::BitField(target, offset, bit_value.into())) @@ -2066,7 +2070,7 @@ impl Engine { ) } else { let chars_len = s.chars().count(); - return EvalAltResult::ErrorStringBounds(chars_len, index, idx_pos).into(); + return Err(EvalAltResult::ErrorStringBounds(chars_len, index, idx_pos).into()); }; Ok(Target::StringChar(target, offset, ch.into())) @@ -2083,7 +2087,7 @@ impl Engine { .map(|(v, _)| v.into()) } - _ => EvalAltResult::ErrorIndexingType( + _ => Err(EvalAltResult::ErrorIndexingType( format!( "{} [{}]", self.map_type_name(target.type_name()), @@ -2091,7 +2095,7 @@ impl Engine { ), Position::NONE, ) - .into(), + .into()), } } @@ -2386,7 +2390,9 @@ impl Engine { ) -> Result<(), Box> { if target.is_read_only() { // Assignment to constant variable - return EvalAltResult::ErrorAssignmentToConstant(root.0.to_string(), root.1).into(); + return Err( + EvalAltResult::ErrorAssignmentToConstant(root.0.to_string(), root.1).into(), + ); } let mut new_val = new_val; @@ -2482,8 +2488,11 @@ impl Engine { .expect("`lhs_ptr` is `Variable`"); if !lhs_ptr.is_ref() { - return EvalAltResult::ErrorAssignmentToConstant(var_name.to_string(), pos) - .into(); + return Err(EvalAltResult::ErrorAssignmentToConstant( + var_name.to_string(), + pos, + ) + .into()); } #[cfg(not(feature = "unchecked"))] @@ -2722,12 +2731,10 @@ impl Engine { if let Some(func) = func { // Add the loop variables let orig_scope_len = scope.len(); - let counter_index = if let Some(Ident { name, .. }) = counter { + let counter_index = counter.as_ref().map(|Ident { name, .. }| { scope.push(unsafe_cast_var_name_to_lifetime(name), 0 as INT); - Some(scope.len() - 1) - } else { - None - }; + scope.len() - 1 + }); scope.push(unsafe_cast_var_name_to_lifetime(name), ()); let index = scope.len() - 1; state.scope_level += 1; @@ -2737,11 +2744,11 @@ impl Engine { if let Some(c) = counter_index { #[cfg(not(feature = "unchecked"))] if x > INT::MAX as usize { - return EvalAltResult::ErrorArithmetic( + return Err(EvalAltResult::ErrorArithmetic( format!("for-loop counter overflow: {}", x), counter.as_ref().expect("`counter` is `Some`").pos, ) - .into(); + .into()); } let mut counter_var = scope @@ -2791,13 +2798,13 @@ impl Engine { scope.rewind(orig_scope_len); Ok(Dynamic::UNIT) } else { - EvalAltResult::ErrorFor(expr.position()).into() + Err(EvalAltResult::ErrorFor(expr.position()).into()) } } // Continue/Break statement Stmt::BreakLoop(options, pos) => { - EvalAltResult::LoopBreak(options.contains(AST_OPTION_BREAK_OUT), *pos).into() + Err(EvalAltResult::LoopBreak(options.contains(AST_OPTION_BREAK_OUT), *pos).into()) } // Namespace-qualified function call @@ -2920,29 +2927,29 @@ impl Engine { // Throw value Stmt::Return(options, Some(expr), pos) if options.contains(AST_OPTION_BREAK_OUT) => { - EvalAltResult::ErrorRuntime( + Err(EvalAltResult::ErrorRuntime( self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)? .flatten(), *pos, ) - .into() + .into()) } // Empty throw Stmt::Return(options, None, pos) if options.contains(AST_OPTION_BREAK_OUT) => { - EvalAltResult::ErrorRuntime(Dynamic::UNIT, *pos).into() + Err(EvalAltResult::ErrorRuntime(Dynamic::UNIT, *pos).into()) } // Return value - Stmt::Return(_, Some(expr), pos) => EvalAltResult::Return( + Stmt::Return(_, Some(expr), pos) => Err(EvalAltResult::Return( self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)? .flatten(), *pos, ) - .into(), + .into()), // Empty return - Stmt::Return(_, None, pos) => EvalAltResult::Return(Dynamic::UNIT, *pos).into(), + Stmt::Return(_, None, pos) => Err(EvalAltResult::Return(Dynamic::UNIT, *pos).into()), // Let/const statement Stmt::Var(expr, x, options, _) => { @@ -3005,7 +3012,7 @@ impl Engine { // Guard against too many modules #[cfg(not(feature = "unchecked"))] if state.num_modules >= self.max_modules() { - return EvalAltResult::ErrorTooManyModules(*_pos).into(); + return Err(EvalAltResult::ErrorTooManyModules(*_pos).into()); } if let Some(path) = self @@ -3034,7 +3041,10 @@ impl Engine { .map(|r| r.resolve(self, source, &path, path_pos)) }) .unwrap_or_else(|| { - EvalAltResult::ErrorModuleNotFound(path.to_string(), path_pos).into() + Err( + EvalAltResult::ErrorModuleNotFound(path.to_string(), path_pos) + .into(), + ) })?; if let Some(name) = export.as_ref().map(|x| x.name.clone()) { @@ -3067,7 +3077,9 @@ impl Engine { if rename.is_empty() { name } else { rename }.clone(), ); } else { - return EvalAltResult::ErrorVariableNotFound(name.to_string(), *pos).into(); + return Err( + EvalAltResult::ErrorVariableNotFound(name.to_string(), *pos).into() + ); } } Ok(Dynamic::UNIT) @@ -3184,11 +3196,11 @@ impl Engine { .max_string_size .map_or(usize::MAX, NonZeroUsize::get) { - return EvalAltResult::ErrorDataTooLarge( + return Err(EvalAltResult::ErrorDataTooLarge( "Length of string".to_string(), Position::NONE, ) - .into(); + .into()); } #[cfg(not(feature = "no_index"))] @@ -3198,8 +3210,11 @@ impl Engine { .max_array_size .map_or(usize::MAX, NonZeroUsize::get) { - return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), Position::NONE) - .into(); + return Err(EvalAltResult::ErrorDataTooLarge( + "Size of array".to_string(), + Position::NONE, + ) + .into()); } #[cfg(not(feature = "no_object"))] @@ -3209,11 +3224,11 @@ impl Engine { .max_map_size .map_or(usize::MAX, NonZeroUsize::get) { - return EvalAltResult::ErrorDataTooLarge( + return Err(EvalAltResult::ErrorDataTooLarge( "Size of object map".to_string(), Position::NONE, ) - .into(); + .into()); } Ok(()) @@ -3230,14 +3245,14 @@ impl Engine { // Guard against too many operations if self.max_operations() > 0 && state.num_operations > self.max_operations() { - return EvalAltResult::ErrorTooManyOperations(pos).into(); + return Err(EvalAltResult::ErrorTooManyOperations(pos).into()); } // Report progress - only in steps if let Some(ref progress) = self.progress { if let Some(token) = progress(state.num_operations) { // Terminate script if progress returns a termination token - return EvalAltResult::ErrorTerminated(token, pos).into(); + return Err(EvalAltResult::ErrorTerminated(token, pos).into()); } } @@ -3248,7 +3263,7 @@ impl Engine { /// /// If a type is registered via [`register_type_with_name`][Engine::register_type_with_name], /// the type name provided for the registration will be used. - #[inline(always)] + #[inline] #[must_use] pub fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str { self.type_names @@ -3258,7 +3273,7 @@ impl Engine { } /// Make a `Box<`[`EvalAltResult`][EvalAltResult::ErrorMismatchDataType]`>`. - #[inline(always)] + #[inline] #[must_use] pub(crate) fn make_type_mismatch_err(&self, typ: &str, pos: Position) -> Box { EvalAltResult::ErrorMismatchDataType( diff --git a/src/engine_api.rs b/src/engine_api.rs index 8ba01d01..50b720d7 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -5,7 +5,6 @@ use crate::engine::{EvalContext, EvalState, Imports}; use crate::fn_call::FnCallArgs; use crate::fn_native::SendSync; use crate::fn_register::RegisterNativeFunction; -use crate::optimize::OptimizationLevel; use crate::parse::ParseState; use crate::{ scope::Scope, Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, Identifier, Module, @@ -1171,7 +1170,12 @@ impl Engine { scope: &Scope, scripts: &[&str], ) -> Result { - self.compile_with_scope_and_optimization_level(scope, scripts, self.optimization_level) + self.compile_with_scope_and_optimization_level( + scope, + scripts, + #[cfg(not(feature = "no_optimize"))] + self.optimization_level, + ) } /// Join a list of strings and compile into an [`AST`] using own scope at a specific optimization level. #[inline] @@ -1179,7 +1183,7 @@ impl Engine { &self, scope: &Scope, scripts: &[&str], - optimization_level: OptimizationLevel, + #[cfg(not(feature = "no_optimize"))] optimization_level: crate::OptimizationLevel, ) -> Result { let (stream, tokenizer_control) = self.lex_raw(scripts, self.token_mapper.as_ref().map(Box::as_ref)); @@ -1188,6 +1192,7 @@ impl Engine { &mut stream.peekable(), &mut state, scope, + #[cfg(not(feature = "no_optimize"))] optimization_level, ) } @@ -1287,7 +1292,7 @@ impl Engine { /// ``` #[cfg(not(feature = "no_std"))] #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))] - #[inline(always)] + #[inline] pub fn compile_file_with_scope( &self, scope: &Scope, @@ -1385,7 +1390,8 @@ impl Engine { &mut stream.peekable(), &mut state, &scope, - OptimizationLevel::None, + #[cfg(not(feature = "no_optimize"))] + crate::OptimizationLevel::None, )?; if has_null { scope.push_constant("null", ()); @@ -1470,7 +1476,13 @@ impl Engine { let mut peekable = stream.peekable(); let mut state = ParseState::new(self, tokenizer_control); - self.parse_global_expr(&mut peekable, &mut state, scope, self.optimization_level) + self.parse_global_expr( + &mut peekable, + &mut state, + scope, + #[cfg(not(feature = "no_optimize"))] + self.optimization_level, + ) } /// Evaluate a script file. /// @@ -1491,7 +1503,7 @@ impl Engine { /// ``` #[cfg(not(feature = "no_std"))] #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))] - #[inline(always)] + #[inline] pub fn eval_file( &self, path: std::path::PathBuf, @@ -1521,7 +1533,7 @@ impl Engine { /// ``` #[cfg(not(feature = "no_std"))] #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))] - #[inline(always)] + #[inline] pub fn eval_file_with_scope( &self, scope: &mut Scope, @@ -1569,7 +1581,7 @@ impl Engine { /// # Ok(()) /// # } /// ``` - #[inline(always)] + #[inline] pub fn eval_with_scope( &self, scope: &mut Scope, @@ -1578,6 +1590,7 @@ impl Engine { let ast = self.compile_with_scope_and_optimization_level( scope, &[script], + #[cfg(not(feature = "no_optimize"))] self.optimization_level, )?; self.eval_ast_with_scope(scope, &ast) @@ -1637,7 +1650,8 @@ impl Engine { &mut stream.peekable(), &mut state, scope, - OptimizationLevel::None, + #[cfg(not(feature = "no_optimize"))] + crate::OptimizationLevel::None, )?; self.eval_ast_with_scope(scope, &ast) @@ -1744,7 +1758,7 @@ impl Engine { /// Not available under `no_std` or `WASM`. #[cfg(not(feature = "no_std"))] #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))] - #[inline(always)] + #[inline] pub fn run_file(&self, path: std::path::PathBuf) -> Result<(), Box> { Self::read_file(path).and_then(|contents| self.run(&contents)) } @@ -1753,7 +1767,7 @@ impl Engine { /// Not available under `no_std` or `WASM`. #[cfg(not(feature = "no_std"))] #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))] - #[inline(always)] + #[inline] pub fn run_file_with_scope( &self, scope: &mut Scope, @@ -1782,6 +1796,7 @@ impl Engine { &mut stream.peekable(), &mut state, scope, + #[cfg(not(feature = "no_optimize"))] self.optimization_level, )?; @@ -2027,7 +2042,7 @@ impl Engine { &self, scope: &Scope, mut ast: AST, - optimization_level: OptimizationLevel, + optimization_level: crate::OptimizationLevel, ) -> AST { #[cfg(not(feature = "no_function"))] let lib = ast diff --git a/src/engine_settings.rs b/src/engine_settings.rs index f1558638..7032f84f 100644 --- a/src/engine_settings.rs +++ b/src/engine_settings.rs @@ -67,7 +67,7 @@ impl Engine { /// /// Not available under `unchecked`. #[cfg(not(feature = "unchecked"))] - #[inline(always)] + #[inline] #[must_use] pub const fn max_operations(&self) -> u64 { if let Some(n) = self.limits.max_operations { @@ -117,7 +117,7 @@ impl Engine { /// /// Not available under `unchecked`. #[cfg(not(feature = "unchecked"))] - #[inline(always)] + #[inline] #[must_use] pub const fn max_expr_depth(&self) -> usize { if let Some(n) = self.limits.max_expr_depth { @@ -131,7 +131,7 @@ impl Engine { /// Not available under `unchecked` or `no_function`. #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_function"))] - #[inline(always)] + #[inline] #[must_use] pub const fn max_function_expr_depth(&self) -> usize { if let Some(n) = self.limits.max_function_expr_depth { @@ -153,7 +153,7 @@ impl Engine { /// /// Not available under `unchecked`. #[cfg(not(feature = "unchecked"))] - #[inline(always)] + #[inline] #[must_use] pub const fn max_string_size(&self) -> usize { if let Some(n) = self.limits.max_string_size { @@ -177,7 +177,7 @@ impl Engine { /// Not available under `unchecked` or `no_index`. #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_index"))] - #[inline(always)] + #[inline] #[must_use] pub const fn max_array_size(&self) -> usize { if let Some(n) = self.limits.max_array_size { @@ -201,7 +201,7 @@ impl Engine { /// Not available under `unchecked` or `no_object`. #[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "no_object"))] - #[inline(always)] + #[inline] #[must_use] pub const fn max_map_size(&self) -> usize { if let Some(n) = self.limits.max_map_size { diff --git a/src/error.rs b/src/error.rs index adc7cf15..4cf608fa 100644 --- a/src/error.rs +++ b/src/error.rs @@ -216,14 +216,14 @@ impl fmt::Display for EvalAltResult { } impl> From for EvalAltResult { - #[inline(always)] + #[inline(never)] fn from(err: T) -> Self { Self::ErrorRuntime(err.as_ref().to_string().into(), Position::NONE) } } impl> From for Box { - #[inline(always)] + #[inline(never)] fn from(err: T) -> Self { EvalAltResult::ErrorRuntime(err.as_ref().to_string().into(), Position::NONE).into() } @@ -444,7 +444,7 @@ impl EvalAltResult { } /// Consume the current [`EvalAltResult`] and return a new one with the specified [`Position`] /// if the current position is [`Position::None`]. - #[inline] + #[inline(never)] #[must_use] pub(crate) fn fill_position(mut self: Box, new_position: Position) -> Box { if self.position().is_none() { @@ -453,10 +453,3 @@ impl EvalAltResult { self } } - -impl From for Result> { - #[inline(always)] - fn from(err: EvalAltResult) -> Self { - Err(err.into()) - } -} diff --git a/src/error_parsing.rs b/src/error_parsing.rs index 1094028c..66b740b6 100644 --- a/src/error_parsing.rs +++ b/src/error_parsing.rs @@ -266,7 +266,7 @@ impl fmt::Display for ParseErrorType { } impl From for ParseErrorType { - #[inline(always)] + #[inline(never)] fn from(err: LexError) -> Self { match err { LexError::StringTooLong(max) => { diff --git a/src/fn_args.rs b/src/fn_args.rs index 6e6f4621..3f6f11de 100644 --- a/src/fn_args.rs +++ b/src/fn_args.rs @@ -57,7 +57,7 @@ pub trait FuncArgs { } impl FuncArgs for Vec { - #[inline(always)] + #[inline] fn parse>(self, container: &mut CONTAINER) { container.extend(self.into_iter().map(Variant::into_dynamic)); } @@ -69,7 +69,7 @@ macro_rules! impl_args { ($($p:ident),*) => { impl<$($p: Variant + Clone),*> FuncArgs for ($($p,)*) { - #[inline(always)] + #[inline] #[allow(unused_variables)] fn parse>(self, container: &mut CONTAINER) { let ($($p,)*) = self; diff --git a/src/fn_call.rs b/src/fn_call.rs index 61911f74..2bafb66b 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -9,7 +9,6 @@ use crate::engine::{ use crate::fn_builtin::{get_builtin_binary_op_fn, get_builtin_op_assignment_fn}; use crate::fn_native::FnAny; use crate::module::NamespaceRef; -use crate::optimize::OptimizationLevel; use crate::{ ast::{Expr, Stmt}, fn_native::CallableFunction, @@ -57,7 +56,7 @@ impl<'a> ArgBackup<'a> { /// # Panics /// /// Panics when `args` is empty. - #[inline(always)] + #[inline] fn change_first_arg_to_copy(&mut self, args: &mut FnCallArgs<'a>) { // Clone the original value. self.value_copy = args[0].clone(); @@ -91,7 +90,7 @@ impl<'a> ArgBackup<'a> { } impl Drop for ArgBackup<'_> { - #[inline(always)] + #[inline] fn drop(&mut self) { // Panic if the shorter lifetime leaks. assert!( @@ -115,11 +114,11 @@ pub fn ensure_no_data_race( .skip(if is_method_call { 1 } else { 0 }) .find(|(_, a)| a.is_locked()) { - return EvalAltResult::ErrorDataRace( + return Err(EvalAltResult::ErrorDataRace( format!("argument #{} of function '{}'", n + 1, fn_name), Position::NONE, ) - .into(); + .into()); } Ok(()) @@ -392,7 +391,7 @@ impl Engine { crate::engine::FN_IDX_GET => { assert!(args.len() == 2); - EvalAltResult::ErrorIndexingType( + Err(EvalAltResult::ErrorIndexingType( format!( "{} [{}]", self.map_type_name(args[0].type_name()), @@ -400,7 +399,7 @@ impl Engine { ), pos, ) - .into() + .into()) } // index setter function not found? @@ -408,7 +407,7 @@ impl Engine { crate::engine::FN_IDX_SET => { assert!(args.len() == 3); - EvalAltResult::ErrorIndexingType( + Err(EvalAltResult::ErrorIndexingType( format!( "{} [{}] = {}", self.map_type_name(args[0].type_name()), @@ -417,7 +416,7 @@ impl Engine { ), pos, ) - .into() + .into()) } // Getter function not found? @@ -425,7 +424,7 @@ impl Engine { _ if name.starts_with(crate::engine::FN_GET) => { assert!(args.len() == 1); - EvalAltResult::ErrorDotExpr( + Err(EvalAltResult::ErrorDotExpr( format!( "Unknown property '{}' - a getter is not registered for type '{}'", &name[crate::engine::FN_GET.len()..], @@ -433,7 +432,7 @@ impl Engine { ), pos, ) - .into() + .into()) } // Setter function not found? @@ -441,7 +440,7 @@ impl Engine { _ if name.starts_with(crate::engine::FN_SET) => { assert!(args.len() == 2); - EvalAltResult::ErrorDotExpr( + Err(EvalAltResult::ErrorDotExpr( format!( "No writable property '{}' - a setter is not registered for type '{}' to handle '{}'", &name[crate::engine::FN_SET.len()..], @@ -450,14 +449,15 @@ impl Engine { ), pos, ) - .into() + .into()) } // Raise error - _ => { - EvalAltResult::ErrorFunctionNotFound(self.gen_call_signature(None, name, args), pos) - .into() - } + _ => Err(EvalAltResult::ErrorFunctionNotFound( + self.gen_call_signature(None, name, args), + pos, + ) + .into()), } } @@ -481,6 +481,7 @@ impl Engine { pos: Position, level: usize, ) -> RhaiResult { + #[inline(never)] fn make_error( name: String, fn_def: &crate::ast::ScriptFnDef, @@ -488,7 +489,7 @@ impl Engine { err: Box, pos: Position, ) -> RhaiResult { - EvalAltResult::ErrorInFunctionCall( + Err(EvalAltResult::ErrorInFunctionCall( name, fn_def .lib @@ -499,7 +500,7 @@ impl Engine { err, pos, ) - .into() + .into()) } #[cfg(not(feature = "unchecked"))] @@ -513,7 +514,7 @@ impl Engine { #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "unchecked"))] if level > self.max_call_levels() { - return EvalAltResult::ErrorStackOverflow(pos).into(); + return Err(EvalAltResult::ErrorStackOverflow(pos).into()); } let orig_scope_level = state.scope_level; @@ -577,7 +578,7 @@ impl Engine { // System errors are passed straight-through mut err if err.is_system_exception() => { err.set_position(pos); - err.into() + Err(err.into()) } // Other errors are wrapped in `ErrorInFunctionCall` _ => make_error(fn_def.name.to_string(), fn_def, state, err, pos), @@ -650,7 +651,7 @@ impl Engine { ) -> Result<(Dynamic, bool), Box> { fn no_method_err(name: &str, pos: Position) -> Result<(Dynamic, bool), Box> { let msg = format!("'{0}' should not be called this way. Try {0}(...);", name); - EvalAltResult::ErrorRuntime(msg.into(), pos).into() + Err(EvalAltResult::ErrorRuntime(msg.into(), pos).into()) } // Check for data race. @@ -857,7 +858,8 @@ impl Engine { let ast = self.compile_with_scope_and_optimization_level( &Default::default(), &[script], - OptimizationLevel::None, + #[cfg(not(feature = "no_optimize"))] + crate::OptimizationLevel::None, )?; // If new functions are defined within the eval string, it is an error @@ -1457,11 +1459,11 @@ impl Engine { Some(f) => unreachable!("unknown function type: {:?}", f), - None => EvalAltResult::ErrorFunctionNotFound( + None => Err(EvalAltResult::ErrorFunctionNotFound( self.gen_call_signature(Some(namespace), fn_name, &args), pos, ) - .into(), + .into()), } } } diff --git a/src/fn_func.rs b/src/fn_func.rs index c465dab6..b33e273f 100644 --- a/src/fn_func.rs +++ b/src/fn_func.rs @@ -96,13 +96,13 @@ macro_rules! def_anonymous_fn { #[cfg(not(feature = "sync"))] type Output = Box Result>>; - #[inline(always)] + #[inline] fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output { let fn_name: SmartString = entry_point.into(); Box::new(move |$($par),*| self.call_fn(&mut Scope::new(), &ast, &fn_name, ($($par,)*))) } - #[inline(always)] + #[inline] fn create_from_script(self, script: &str, entry_point: &str) -> Result { let ast = self.compile(script)?; Ok(Func::<($($par,)*), RET>::create_from_ast(self, ast, entry_point)) diff --git a/src/fn_native.rs b/src/fn_native.rs index 9fa9d008..ac5ad4d5 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -144,14 +144,14 @@ impl<'a> NativeCallContext<'a> { /// /// Not available under `no_module`. #[cfg(not(feature = "no_module"))] - #[inline(always)] + #[inline] pub fn iter_imports(&self) -> impl Iterator { self.mods.iter().flat_map(|&m| m.iter()) } /// Get an iterator over the current set of modules imported via `import` statements. #[cfg(not(feature = "no_module"))] #[allow(dead_code)] - #[inline(always)] + #[inline] pub(crate) fn iter_imports_raw( &self, ) -> impl Iterator)> { @@ -169,7 +169,7 @@ impl<'a> NativeCallContext<'a> { self.mods } /// Get an iterator over the namespaces containing definitions of all script-defined functions. - #[inline(always)] + #[inline] pub fn iter_namespaces(&self) -> impl Iterator { self.lib.iter().cloned() } @@ -183,6 +183,9 @@ impl<'a> NativeCallContext<'a> { } /// Call a function inside the call context. /// + /// If `is_method_call` is [`true`], the first argument is assumed to be the + /// `this` pointer for a script-defined function (or the object of a method call). + /// /// # WARNING /// /// All arguments may be _consumed_, meaning that they may be replaced by `()`. @@ -191,48 +194,39 @@ impl<'a> NativeCallContext<'a> { /// Do not use the arguments after this call. If they are needed afterwards, /// clone them _before_ calling this function. /// - /// If `is_method` is [`true`], the first argument is assumed to be passed + /// If `is_ref_mut` is [`true`], the first argument is assumed to be passed /// by reference and is not consumed. - #[inline(always)] - pub fn call_fn_dynamic_raw( + pub fn call_fn_raw( &self, - fn_name: impl AsRef, + fn_name: &str, + is_ref_mut: bool, is_method_call: bool, args: &mut [&mut Dynamic], - ) -> RhaiResult { - fn call_fn_dynamic_inner( - context: &NativeCallContext, - is_method_call: bool, - fn_name: &str, - args: &mut [&mut Dynamic], - ) -> Result> { - let hash = if is_method_call { - FnCallHashes::from_script_and_native( - calc_fn_hash(fn_name, args.len() - 1), - calc_fn_hash(fn_name, args.len()), - ) - } else { - FnCallHashes::from_script(calc_fn_hash(fn_name, args.len())) - }; - context - .engine() - .exec_fn_call( - &mut context.mods.cloned().unwrap_or_default(), - &mut Default::default(), - context.lib, - fn_name, - hash, - args, - is_method_call, - is_method_call, - Position::NONE, - None, - 0, - ) - .map(|(r, _)| r) - } + ) -> Result> { + let hash = if is_method_call { + FnCallHashes::from_script_and_native( + calc_fn_hash(fn_name, args.len() - 1), + calc_fn_hash(fn_name, args.len()), + ) + } else { + FnCallHashes::from_script(calc_fn_hash(fn_name, args.len())) + }; - call_fn_dynamic_inner(self, is_method_call, fn_name.as_ref(), args) + self.engine() + .exec_fn_call( + &mut self.mods.cloned().unwrap_or_default(), + &mut Default::default(), + self.lib, + fn_name, + hash, + args, + is_ref_mut, + is_method_call, + Position::NONE, + None, + 0, + ) + .map(|(r, _)| r) } } @@ -245,7 +239,7 @@ pub fn shared_make_mut(value: &mut Shared) -> &mut T { } /// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise. -#[inline(always)] +#[inline] #[must_use] pub fn shared_take_or_clone(value: Shared) -> T { shared_try_take(value).unwrap_or_else(|v| v.as_ref().clone()) @@ -262,7 +256,7 @@ pub fn shared_try_take(value: Shared) -> Result> { /// # Panics /// /// Panics if the resource is shared (i.e. has other outstanding references). -#[inline(always)] +#[inline] #[must_use] pub fn shared_take(value: Shared) -> T { shared_try_take(value) diff --git a/src/fn_ptr.rs b/src/fn_ptr.rs index 3b9350cb..e0140579 100644 --- a/src/fn_ptr.rs +++ b/src/fn_ptr.rs @@ -69,7 +69,7 @@ impl FnPtr { self } /// Set curried arguments to the function pointer. - #[inline(always)] + #[inline] pub fn set_curry(&mut self, values: impl IntoIterator) -> &mut Self { self.1 = values.into_iter().collect(); self @@ -130,7 +130,7 @@ impl FnPtr { } args.extend(arg_values.iter_mut()); - ctx.call_fn_dynamic_raw(self.fn_name(), is_method, &mut args) + ctx.call_fn_raw(self.fn_name(), is_method, is_method, &mut args) } } @@ -148,7 +148,7 @@ impl TryFrom for FnPtr { if is_valid_identifier(value.chars()) { Ok(Self(value, Default::default())) } else { - EvalAltResult::ErrorFunctionNotFound(value.to_string(), Position::NONE).into() + Err(EvalAltResult::ErrorFunctionNotFound(value.to_string(), Position::NONE).into()) } } } diff --git a/src/fn_register.rs b/src/fn_register.rs index 776bace3..fbc74237 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -123,7 +123,7 @@ macro_rules! def_register { #[inline(always)] fn into_callable_function(self) -> CallableFunction { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) { - return EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into()); } // The arguments are assumed to be of the correct number and types! @@ -151,7 +151,7 @@ macro_rules! def_register { #[inline(always)] fn into_callable_function(self) -> CallableFunction { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) { - return EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into()); } // The arguments are assumed to be of the correct number and types! @@ -179,7 +179,7 @@ macro_rules! def_register { #[inline(always)] fn into_callable_function(self) -> CallableFunction { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) { - return EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into()); } // The arguments are assumed to be of the correct number and types! @@ -204,7 +204,7 @@ macro_rules! def_register { #[inline(always)] fn into_callable_function(self) -> CallableFunction { CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { if args.len() == 2 && args[0].is_read_only() && is_setter(ctx.fn_name()) { - return EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into(); + return Err(EvalAltResult::ErrorAssignmentToConstant(Default::default(), Position::NONE).into()); } // The arguments are assumed to be of the correct number and types! diff --git a/src/immutable_string.rs b/src/immutable_string.rs index 8c146897..53ccdab5 100644 --- a/src/immutable_string.rs +++ b/src/immutable_string.rs @@ -90,26 +90,29 @@ impl Borrow for ImmutableString { impl From<&str> for ImmutableString { #[inline(always)] fn from(value: &str) -> Self { - Self(Into::::into(value).into()) + let value: SmartString = value.into(); + Self(value.into()) } } impl From<&String> for ImmutableString { #[inline(always)] fn from(value: &String) -> Self { - Self(Into::::into(value).into()) + let value: SmartString = value.into(); + Self(value.into()) } } impl From for ImmutableString { #[inline(always)] fn from(value: String) -> Self { - Self(Into::::into(value).into()) + let value: SmartString = value.into(); + Self(value.into()) } } #[cfg(not(feature = "no_smartstring"))] impl From<&SmartString> for ImmutableString { #[inline(always)] fn from(value: &SmartString) -> Self { - Self(Into::::into(value.as_str()).into()) + Self(value.clone().into()) } } #[cfg(not(feature = "no_smartstring"))] @@ -137,33 +140,34 @@ impl FromStr for ImmutableString { #[inline(always)] fn from_str(s: &str) -> Result { - Ok(Self(Into::::into(s).into())) + let s: SmartString = s.into(); + Ok(Self(s.into())) } } impl FromIterator for ImmutableString { - #[inline(always)] + #[inline] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect::().into()) } } impl<'a> FromIterator<&'a char> for ImmutableString { - #[inline(always)] + #[inline] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().cloned().collect::().into()) } } impl<'a> FromIterator<&'a str> for ImmutableString { - #[inline(always)] + #[inline] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect::().into()) } } impl<'a> FromIterator for ImmutableString { - #[inline(always)] + #[inline] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect::().into()) } @@ -171,7 +175,7 @@ impl<'a> FromIterator for ImmutableString { #[cfg(not(feature = "no_smartstring"))] impl<'a> FromIterator for ImmutableString { - #[inline(always)] + #[inline] fn from_iter>(iter: T) -> Self { Self(iter.into_iter().collect::().into()) } @@ -278,7 +282,7 @@ impl Add<&str> for &ImmutableString { } impl AddAssign<&str> for ImmutableString { - #[inline(always)] + #[inline] fn add_assign(&mut self, rhs: &str) { if !rhs.is_empty() { self.make_mut().push_str(rhs); @@ -324,7 +328,8 @@ impl AddAssign for ImmutableString { fn add_assign(&mut self, rhs: String) { if !rhs.is_empty() { if self.is_empty() { - self.0 = Into::::into(rhs).into(); + let rhs: SmartString = rhs.into(); + self.0 = rhs.into(); } else { self.make_mut().push_str(&rhs); } @@ -335,7 +340,7 @@ impl AddAssign for ImmutableString { impl Add for ImmutableString { type Output = Self; - #[inline(always)] + #[inline] fn add(mut self, rhs: char) -> Self::Output { self.make_mut().push(rhs); self @@ -345,7 +350,7 @@ impl Add for ImmutableString { impl Add for &ImmutableString { type Output = ImmutableString; - #[inline(always)] + #[inline] fn add(self, rhs: char) -> Self::Output { let mut s = self.clone(); s.make_mut().push(rhs); @@ -354,7 +359,7 @@ impl Add for &ImmutableString { } impl AddAssign for ImmutableString { - #[inline(always)] + #[inline] fn add_assign(&mut self, rhs: char) { self.make_mut().push(rhs); } @@ -397,7 +402,8 @@ impl SubAssign<&ImmutableString> for ImmutableString { if self.is_empty() { self.0 = rhs.0.clone(); } else { - self.0 = Into::::into(self.replace(rhs.as_str(), "")).into(); + let rhs: SmartString = self.replace(rhs.as_str(), "").into(); + self.0 = rhs.into(); } } } @@ -410,7 +416,8 @@ impl SubAssign for ImmutableString { if self.is_empty() { self.0 = rhs.0; } else { - self.0 = Into::::into(self.replace(rhs.as_str(), "")).into(); + let rhs: SmartString = self.replace(rhs.as_str(), "").into(); + self.0 = rhs.into(); } } } @@ -447,9 +454,10 @@ impl Sub for &ImmutableString { } impl SubAssign for ImmutableString { - #[inline(always)] + #[inline] fn sub_assign(&mut self, rhs: String) { - self.0 = Into::::into(self.replace(&rhs, "")).into(); + let rhs: SmartString = self.replace(&rhs, "").into(); + self.0 = rhs.into(); } } @@ -472,9 +480,10 @@ impl Sub for &ImmutableString { } impl SubAssign for ImmutableString { - #[inline(always)] + #[inline] fn sub_assign(&mut self, rhs: char) { - self.0 = Into::::into(self.replace(rhs, "")).into(); + let rhs: SmartString = self.replace(rhs, "").into(); + self.0 = rhs.into(); } } @@ -527,7 +536,7 @@ impl ImmutableString { } /// Consume the [`ImmutableString`] and convert it into a [`String`]. /// If there are other references to the same string, a cloned copy is returned. - #[inline(always)] + #[inline] pub fn into_owned(mut self) -> String { self.make_mut(); // Make sure it is unique reference shared_take(self.0).into() // Should succeed diff --git a/src/lib.rs b/src/lib.rs index 1595116c..4a89ced2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,7 @@ mod fn_ptr; mod fn_register; mod immutable_string; mod module; +#[cfg(not(feature = "no_optimize"))] mod optimize; pub mod packages; mod parse; diff --git a/src/module/mod.rs b/src/module/mod.rs index baa9c7fb..0a9ebe39 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -204,7 +204,7 @@ impl AsRef for Module { impl> Add for &Module { type Output = Module; - #[inline(always)] + #[inline] fn add(self, rhs: M) -> Self::Output { let mut module = self.clone(); module.merge(rhs.as_ref()); @@ -240,7 +240,7 @@ impl Module { /// module.set_var("answer", 42_i64); /// assert_eq!(module.get_var_value::("answer").expect("answer should exist"), 42); /// ``` - #[inline(always)] + #[inline] #[must_use] pub fn new() -> Self { Self { @@ -269,7 +269,7 @@ impl Module { /// module.set_id("hello"); /// assert_eq!(module.id(), Some("hello")); /// ``` - #[inline(always)] + #[inline] #[must_use] pub fn id(&self) -> Option<&str> { self.id_raw().map(|s| s.as_str()) @@ -365,7 +365,7 @@ impl Module { /// Generate signatures for all the non-private functions in the [`Module`]. /// Exported under the `metadata` feature only. #[cfg(feature = "metadata")] - #[inline(always)] + #[inline] pub fn gen_fn_signatures(&self) -> impl Iterator + '_ { self.functions .values() @@ -402,7 +402,7 @@ impl Module { /// module.set_var("answer", 42_i64); /// assert_eq!(module.get_var_value::("answer").expect("answer should exist"), 42); /// ``` - #[inline(always)] + #[inline] #[must_use] pub fn get_var_value(&self, name: &str) -> Option { self.get_var(name).and_then(Dynamic::try_cast::) @@ -559,7 +559,7 @@ impl Module { /// module.set_sub_module("question", sub_module); /// assert!(module.get_sub_module("question").is_some()); /// ``` - #[inline(always)] + #[inline] #[must_use] pub fn get_sub_module(&self, name: &str) -> Option<&Module> { self.modules.get(name).map(|m| m.as_ref()) @@ -1113,7 +1113,7 @@ impl Module { /// Get a Rust function. /// /// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call. - #[inline(always)] + #[inline] #[must_use] pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> { self.functions.get(&hash_fn).map(|f| f.func.as_ref()) @@ -1131,7 +1131,7 @@ impl Module { /// Get a namespace-qualified function. /// /// The [`u64`] hash is calculated by [`build_index`][Module::build_index]. - #[inline(always)] + #[inline] #[must_use] pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> { self.all_functions @@ -1289,19 +1289,19 @@ impl Module { } /// Get an iterator to the sub-modules in the [`Module`]. - #[inline(always)] + #[inline] pub fn iter_sub_modules(&self) -> impl Iterator)> { self.modules.iter().map(|(k, m)| (k.as_str(), m.clone())) } /// Get an iterator to the variables in the [`Module`]. - #[inline(always)] + #[inline] pub fn iter_var(&self) -> impl Iterator { self.variables.iter().map(|(k, v)| (k.as_str(), v)) } /// Get an iterator to the functions in the [`Module`]. - #[inline(always)] + #[inline] #[allow(dead_code)] pub(crate) fn iter_fn(&self) -> impl Iterator { self.functions.values().map(Box::as_ref) @@ -1316,7 +1316,7 @@ impl Module { /// 4) Number of parameters. /// 5) Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef]. #[cfg(not(feature = "no_function"))] - #[inline(always)] + #[inline] pub(crate) fn iter_script_fn( &self, ) -> impl Iterator< @@ -1351,7 +1351,7 @@ impl Module { /// 4) Number of parameters. #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "internals"))] - #[inline(always)] + #[inline] pub fn iter_script_fn_info( &self, ) -> impl Iterator { @@ -1610,7 +1610,7 @@ impl Module { } /// Set a type iterator into the [`Module`]. - #[inline(always)] + #[inline] pub fn set_iterable(&mut self) -> &mut Self where T: Variant + Clone + IntoIterator, @@ -1622,7 +1622,7 @@ impl Module { } /// Set an iterator type into the [`Module`] as a type iterator. - #[inline(always)] + #[inline] pub fn set_iterator(&mut self) -> &mut Self where T: Variant + Clone + Iterator, @@ -1634,14 +1634,14 @@ impl Module { } /// Get the specified type iterator. - #[inline(always)] + #[inline] #[must_use] pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option { self.all_type_iterators.get(&id).cloned() } /// Get the specified type iterator. - #[inline(always)] + #[inline] #[must_use] pub(crate) fn get_iter(&self, id: TypeId) -> Option { self.type_iterators.get(&id).cloned() @@ -1709,8 +1709,7 @@ impl DerefMut for NamespaceRef { impl From> for NamespaceRef { #[inline(always)] - fn from(path: StaticVec) -> Self { - let mut path = path; + fn from(mut path: StaticVec) -> Self { path.shrink_to_fit(); Self { index: None, path } } diff --git a/src/module/resolvers/collection.rs b/src/module/resolvers/collection.rs index 55087afe..6a61ff3f 100644 --- a/src/module/resolvers/collection.rs +++ b/src/module/resolvers/collection.rs @@ -76,7 +76,7 @@ impl ModuleResolversCollection { self.0.remove(index) } /// Get an iterator of all the [module resolvers][ModuleResolver]. - #[inline(always)] + #[inline] pub fn iter(&self) -> impl Iterator { self.0.iter().map(|v| v.as_ref()) } @@ -100,7 +100,7 @@ impl ModuleResolversCollection { } /// Add another [`ModuleResolversCollection`] to the end of this collection. /// The other [`ModuleResolversCollection`] is consumed. - #[inline(always)] + #[inline] pub fn append(&mut self, other: Self) -> &mut Self { self.0.extend(other.0.into_iter()); self @@ -136,7 +136,7 @@ impl ModuleResolver for ModuleResolversCollection { } } - EvalAltResult::ErrorModuleNotFound(path.into(), pos).into() + Err(EvalAltResult::ErrorModuleNotFound(path.into(), pos).into()) } } diff --git a/src/module/resolvers/dummy.rs b/src/module/resolvers/dummy.rs index 15c706f2..904f48ce 100644 --- a/src/module/resolvers/dummy.rs +++ b/src/module/resolvers/dummy.rs @@ -45,6 +45,6 @@ impl ModuleResolver for DummyModuleResolver { path: &str, pos: Position, ) -> Result, Box> { - EvalAltResult::ErrorModuleNotFound(path.into(), pos).into() + Err(EvalAltResult::ErrorModuleNotFound(path.into(), pos).into()) } } diff --git a/src/module/resolvers/file.rs b/src/module/resolvers/file.rs index f3b06113..276243fa 100644 --- a/src/module/resolvers/file.rs +++ b/src/module/resolvers/file.rs @@ -215,7 +215,7 @@ impl FileModuleResolver { return self.cache.write().unwrap().contains_key(&file_path); } /// Empty the internal cache. - #[inline(always)] + #[inline] pub fn clear_cache(&mut self) -> &mut Self { #[cfg(not(feature = "sync"))] self.cache.borrow_mut().clear(); diff --git a/src/module/resolvers/stat.rs b/src/module/resolvers/stat.rs index 0b555884..a5b4d0c9 100644 --- a/src/module/resolvers/stat.rs +++ b/src/module/resolvers/stat.rs @@ -48,7 +48,7 @@ impl StaticModuleResolver { Default::default() } /// Add a [module][Module] keyed by its path. - #[inline(always)] + #[inline] pub fn insert(&mut self, path: impl Into, mut module: Module) { module.build_index(); self.0.insert(path.into(), module.into()); @@ -65,17 +65,17 @@ impl StaticModuleResolver { self.0.contains_key(path) } /// Get an iterator of all the [modules][Module]. - #[inline(always)] + #[inline] pub fn iter(&self) -> impl Iterator)> { self.0.iter().map(|(k, v)| (k.as_str(), v)) } /// Get a mutable iterator of all the [modules][Module]. - #[inline(always)] + #[inline] pub fn iter_mut(&mut self) -> impl Iterator)> { self.0.iter_mut().map(|(k, v)| (k.as_str(), v)) } /// Get an iterator of all the [module][Module] paths. - #[inline(always)] + #[inline] pub fn paths(&self) -> impl Iterator { self.0.keys().map(|s| s.as_str()) } @@ -105,7 +105,7 @@ impl StaticModuleResolver { /// The other [`StaticModuleResolver`] is consumed. /// /// Existing modules of the same path name are overwritten. - #[inline(always)] + #[inline] pub fn merge(&mut self, other: Self) -> &mut Self { if !other.is_empty() { self.0.extend(other.0.into_iter()); @@ -124,7 +124,7 @@ impl IntoIterator for StaticModuleResolver { } impl ModuleResolver for StaticModuleResolver { - #[inline(always)] + #[inline] fn resolve( &self, _: &Engine, diff --git a/src/optimize.rs b/src/optimize.rs index 22878f5b..8479ecd4 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -123,7 +123,7 @@ impl<'a> OptimizerState<'a> { }) } /// Call a registered function - #[inline(always)] + #[inline] pub fn call_fn_with_constant_arguments( &self, fn_name: &str, diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index 66c05978..f387d862 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -9,7 +9,7 @@ use std::prelude::v1::*; #[cfg(not(feature = "no_float"))] use num_traits::Float; -#[inline(always)] +#[inline(never)] pub fn make_err(msg: impl Into) -> Box { EvalAltResult::ErrorArithmetic(msg.into(), Position::NONE).into() } diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index f119bc0e..51c1bcc0 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -79,8 +79,11 @@ mod array_functions { // Check if array will be over max size limit #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_array_size() > 0 && (len as usize) > _ctx.engine().max_array_size() { - return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), Position::NONE) - .into(); + return Err(EvalAltResult::ErrorDataTooLarge( + "Size of array".to_string(), + Position::NONE, + ) + .into()); } if len as usize > array.len() { @@ -244,34 +247,45 @@ mod array_functions { ctx: NativeCallContext, array: &mut Array, mapper: FnPtr, + ) -> Result> { + map_with_fn_name(ctx, array, mapper.fn_name()) + } + #[rhai_fn(name = "map", return_raw, pure)] + pub fn map_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + mapper: &str, ) -> Result> { if array.is_empty() { - return Ok(array.clone()); + return Ok(Array::new()); } let mut ar = Array::with_capacity(array.len()); + let mut index_val = Dynamic::UNIT; - for (i, item) in array.iter().enumerate() { - ar.push( - mapper - .call_dynamic(&ctx, None, [item.clone()]) - .or_else(|err| match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(mapper.fn_name()) => - { - mapper.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) - } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( + for (i, item) in array.iter_mut().enumerate() { + let mut args = [item, &mut index_val]; + + ar.push(match ctx.call_fn_raw(mapper, true, false, &mut args[..1]) { + Ok(r) => r, + Err(err) => match *err { + EvalAltResult::ErrorFunctionNotFound(fn_sig, _) + if fn_sig.starts_with(mapper) => + { + *args[1] = Dynamic::from(i as INT); + ctx.call_fn_raw(mapper, true, false, &mut args)? + } + _ => { + return Err(EvalAltResult::ErrorInFunctionCall( "map".to_string(), ctx.source().unwrap_or("").to_string(), err, Position::NONE, - )) - })?, - ); + ) + .into()) + } + }, + }); } Ok(ar) @@ -281,36 +295,50 @@ mod array_functions { ctx: NativeCallContext, array: &mut Array, filter: FnPtr, + ) -> Result> { + filter_with_fn_name(ctx, array, filter.fn_name()) + } + #[rhai_fn(name = "filter", return_raw, pure)] + pub fn filter_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, ) -> Result> { if array.is_empty() { return Ok(array.clone()); } let mut ar = Array::new(); + let mut index_val = Dynamic::UNIT; - for (i, item) in array.iter().enumerate() { - if filter - .call_dynamic(&ctx, None, [item.clone()]) - .or_else(|err| match *err { + for (i, item) in array.iter_mut().enumerate() { + let mut args = [item, &mut index_val]; + + let keep = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { + Ok(r) => r, + Err(err) => match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter.fn_name()) => + if fn_sig.starts_with(filter) => { - filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) + *args[1] = Dynamic::from(i as INT); + ctx.call_fn_raw(filter, true, false, &mut args)? } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "filter".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })? - .as_bool() - .unwrap_or(false) - { - ar.push(item.clone()); + _ => { + return Err(EvalAltResult::ErrorInFunctionCall( + "filter".to_string(), + ctx.source().unwrap_or("").to_string(), + err, + Position::NONE, + ) + .into()) + } + }, + } + .as_bool() + .unwrap_or(false); + + if keep { + ar.push(args[0].clone()); } } @@ -328,7 +356,7 @@ mod array_functions { for item in array.iter_mut() { if ctx - .call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()]) + .call_fn_raw(OP_EQUALS, true, false, &mut [item, &mut value.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _) if fn_sig.starts_with(OP_EQUALS) => @@ -387,7 +415,7 @@ mod array_functions { for (i, item) in array.iter_mut().enumerate().skip(start) { if ctx - .call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()]) + .call_fn_raw(OP_EQUALS, true, false, &mut [item, &mut value.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _) if fn_sig.starts_with(OP_EQUALS) => @@ -411,6 +439,14 @@ mod array_functions { Ok(-1 as INT) } #[rhai_fn(name = "index_of", return_raw, pure)] + pub fn index_of_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, + ) -> Result> { + index_of_filter(ctx, array, FnPtr::new(filter)?) + } + #[rhai_fn(name = "index_of", return_raw, pure)] pub fn index_of_filter( ctx: NativeCallContext, array: &mut Array, @@ -428,6 +464,15 @@ mod array_functions { array: &mut Array, filter: FnPtr, start: INT, + ) -> Result> { + index_of_with_fn_name_filter_starting_from(ctx, array, filter.fn_name(), start) + } + #[rhai_fn(name = "index_of", return_raw, pure)] + pub fn index_of_with_fn_name_filter_starting_from( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, + start: INT, ) -> Result> { if array.is_empty() { return Ok(-1); @@ -444,28 +489,35 @@ mod array_functions { start as usize }; - for (i, item) in array.iter().enumerate().skip(start) { - if filter - .call_dynamic(&ctx, None, [item.clone()]) - .or_else(|err| match *err { + let mut index_val = Dynamic::UNIT; + + for (i, item) in array.iter_mut().enumerate().skip(start) { + let mut args = [item, &mut index_val]; + + let found = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { + Ok(r) => r, + Err(err) => match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter.fn_name()) => + if fn_sig.starts_with(filter) => { - filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) + *args[1] = Dynamic::from(i as INT); + ctx.call_fn_raw(filter, true, false, &mut args)? } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "index_of".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })? - .as_bool() - .unwrap_or(false) - { + _ => { + return Err(EvalAltResult::ErrorInFunctionCall( + "index_of".to_string(), + ctx.source().unwrap_or("").to_string(), + err, + Position::NONE, + ) + .into()) + } + }, + } + .as_bool() + .unwrap_or(false); + + if found { return Ok(i as INT); } } @@ -477,33 +529,48 @@ mod array_functions { ctx: NativeCallContext, array: &mut Array, filter: FnPtr, + ) -> Result> { + some_with_fn_name(ctx, array, filter.fn_name()) + } + #[rhai_fn(name = "some", return_raw, pure)] + pub fn some_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, ) -> Result> { if array.is_empty() { return Ok(false); } - for (i, item) in array.iter().enumerate() { - if filter - .call_dynamic(&ctx, None, [item.clone()]) - .or_else(|err| match *err { + let mut index_val = Dynamic::UNIT; + + for (i, item) in array.iter_mut().enumerate() { + let mut args = [item, &mut index_val]; + + let found = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { + Ok(r) => r, + Err(err) => match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter.fn_name()) => + if fn_sig.starts_with(filter) => { - filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) + *args[1] = Dynamic::from(i as INT); + ctx.call_fn_raw(filter, true, false, &mut args)? } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "some".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })? - .as_bool() - .unwrap_or(false) - { + _ => { + return Err(EvalAltResult::ErrorInFunctionCall( + "some".to_string(), + ctx.source().unwrap_or("").to_string(), + err, + Position::NONE, + ) + .into()) + } + }, + } + .as_bool() + .unwrap_or(false); + + if found { return Ok(true); } } @@ -515,73 +582,102 @@ mod array_functions { ctx: NativeCallContext, array: &mut Array, filter: FnPtr, + ) -> Result> { + all_with_fn_name(ctx, array, filter.fn_name()) + } + #[rhai_fn(name = "all", return_raw, pure)] + pub fn all_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, ) -> Result> { if array.is_empty() { return Ok(true); } - for (i, item) in array.iter().enumerate() { - if !filter - .call_dynamic(&ctx, None, [item.clone()]) - .or_else(|err| match *err { + let mut index_val = Dynamic::UNIT; + + for (i, item) in array.iter_mut().enumerate() { + let mut args = [item, &mut index_val]; + + let found = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { + Ok(r) => r, + Err(err) => match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter.fn_name()) => + if fn_sig.starts_with(filter) => { - filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) + *args[1] = Dynamic::from(i as INT); + ctx.call_fn_raw(filter, true, false, &mut args)? } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "all".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })? - .as_bool() - .unwrap_or(false) - { + _ => { + return Err(EvalAltResult::ErrorInFunctionCall( + "all".to_string(), + ctx.source().unwrap_or("").to_string(), + err, + Position::NONE, + ) + .into()) + } + }, + } + .as_bool() + .unwrap_or(false); + + if !found { return Ok(false); } } Ok(true) } + #[rhai_fn(return_raw)] + pub fn dedup(ctx: NativeCallContext, array: &mut Array) -> Result<(), Box> { + dedup_with_fn_name(ctx, array, OP_EQUALS) + } + #[rhai_fn(name = "dedup", return_raw)] + pub fn dedup_by_comparer( + ctx: NativeCallContext, + array: &mut Array, + comparer: FnPtr, + ) -> Result<(), Box> { + dedup_with_fn_name(ctx, array, comparer.fn_name()) + } + #[rhai_fn(name = "dedup", return_raw)] + fn dedup_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + comparer: &str, + ) -> Result<(), Box> { + if array.is_empty() { + return Ok(()); + } + + array.dedup_by(|x, y| { + let mut args = [x, &mut y.clone()]; + + ctx.call_fn_raw(comparer, true, false, &mut args) + .unwrap_or_else(|_| Dynamic::FALSE) + .as_bool() + .unwrap_or(false) + }); + + Ok(()) + } #[rhai_fn(return_raw, pure)] pub fn reduce( ctx: NativeCallContext, array: &mut Array, reducer: FnPtr, ) -> Result> { - if array.is_empty() { - return Ok(Dynamic::UNIT); - } - - let mut result = Dynamic::UNIT; - - for (i, item) in array.iter().enumerate() { - result = reducer - .call_dynamic(&ctx, None, [result.clone(), item.clone()]) - .or_else(|err| match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(reducer.fn_name()) => - { - reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) - } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "reduce".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })?; - } - - Ok(result) + reduce_with_fn_name(ctx, array, reducer.fn_name()) + } + #[rhai_fn(name = "reduce", return_raw, pure)] + pub fn reduce_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + reducer: &str, + ) -> Result> { + reduce_with_fn_name_with_initial(ctx, array, reducer, Dynamic::UNIT) } #[rhai_fn(name = "reduce", return_raw, pure)] pub fn reduce_with_initial( @@ -589,21 +685,35 @@ mod array_functions { array: &mut Array, reducer: FnPtr, initial: Dynamic, + ) -> Result> { + reduce_with_fn_name_with_initial(ctx, array, reducer.fn_name(), initial) + } + #[rhai_fn(name = "reduce", return_raw, pure)] + pub fn reduce_with_fn_name_with_initial( + ctx: NativeCallContext, + array: &mut Array, + reducer: &str, + initial: Dynamic, ) -> Result> { if array.is_empty() { return Ok(initial); } let mut result = initial; + let mut index_val = Dynamic::UNIT; - for (i, item) in array.iter().enumerate() { - result = reducer - .call_dynamic(&ctx, None, [result.clone(), item.clone()]) + for (i, item) in array.iter_mut().enumerate() { + let mut args = [&mut result, &mut item.clone(), &mut index_val]; + + result = ctx + .call_fn_raw(reducer, true, false, &mut args[..2]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(reducer.fn_name()) => + if fn_sig.starts_with(reducer) => { - reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) + *args[1] = item.clone(); + *args[2] = Dynamic::from(i as INT); + ctx.call_fn_raw(reducer, true, false, &mut args) } _ => Err(err), }) @@ -625,34 +735,15 @@ mod array_functions { array: &mut Array, reducer: FnPtr, ) -> Result> { - if array.is_empty() { - return Ok(Dynamic::UNIT); - } - - let mut result = Dynamic::UNIT; - - for (i, item) in array.iter().enumerate().rev() { - result = reducer - .call_dynamic(&ctx, None, [result.clone(), item.clone()]) - .or_else(|err| match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(reducer.fn_name()) => - { - reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) - } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "reduce_rev".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })?; - } - - Ok(result) + reduce_rev_with_fn_name(ctx, array, reducer.fn_name()) + } + #[rhai_fn(name = "reduce_rev", return_raw, pure)] + pub fn reduce_rev_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + reducer: &str, + ) -> Result> { + reduce_rev_with_fn_name_with_initial(ctx, array, reducer, Dynamic::UNIT) } #[rhai_fn(name = "reduce_rev", return_raw, pure)] pub fn reduce_rev_with_initial( @@ -660,21 +751,35 @@ mod array_functions { array: &mut Array, reducer: FnPtr, initial: Dynamic, + ) -> Result> { + reduce_rev_with_fn_name_with_initial(ctx, array, reducer.fn_name(), initial) + } + #[rhai_fn(name = "reduce_rev", return_raw, pure)] + pub fn reduce_rev_with_fn_name_with_initial( + ctx: NativeCallContext, + array: &mut Array, + reducer: &str, + initial: Dynamic, ) -> Result> { if array.is_empty() { return Ok(initial); } let mut result = initial; + let mut index_val = Dynamic::UNIT; - for (i, item) in array.iter().enumerate().rev() { - result = reducer - .call_dynamic(&ctx, None, [result.clone(), item.clone()]) + for (i, item) in array.iter_mut().enumerate().rev() { + let mut args = [&mut result, &mut item.clone(), &mut index_val]; + + result = ctx + .call_fn_raw(reducer, true, false, &mut args[..2]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(reducer.fn_name()) => + if fn_sig.starts_with(reducer) => { - reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) + *args[1] = item.clone(); + *args[2] = Dynamic::from(i as INT); + ctx.call_fn_raw(reducer, true, false, &mut args) } _ => Err(err), }) @@ -690,13 +795,21 @@ mod array_functions { Ok(result) } + #[rhai_fn(name = "sort", return_raw)] + pub fn sort_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + comparer: &str, + ) -> Result<(), Box> { + sort(ctx, array, FnPtr::new(comparer)?) + } #[rhai_fn(return_raw)] pub fn sort( ctx: NativeCallContext, array: &mut Array, comparer: FnPtr, ) -> Result<(), Box> { - if array.is_empty() { + if array.len() <= 1 { return Ok(()); } @@ -716,52 +829,155 @@ mod array_functions { Ok(()) } - #[rhai_fn(return_raw)] + #[rhai_fn(name = "sort", return_raw)] + pub fn sort_with_builtin(array: &mut Array) -> Result<(), Box> { + if array.len() <= 1 { + return Ok(()); + } + + let type_id = array[0].type_id(); + + if array.iter().any(|a| a.type_id() != type_id) { + return Err(EvalAltResult::ErrorFunctionNotFound( + "sort() cannot be called with elements of different types".into(), + Position::NONE, + ) + .into()); + } + + if type_id == TypeId::of::() { + array.sort_by(|a, b| { + let a = a.as_int().expect("a is INT"); + let b = b.as_int().expect("b is INT"); + a.cmp(&b) + }); + return Ok(()); + } + if type_id == TypeId::of::() { + array.sort_by(|a, b| { + let a = a.as_char().expect("a is char"); + let b = b.as_char().expect("b is char"); + a.cmp(&b) + }); + return Ok(()); + } + #[cfg(not(feature = "no_float"))] + if type_id == TypeId::of::() { + array.sort_by(|a, b| { + let a = a.as_float().expect("a is FLOAT"); + let b = b.as_float().expect("b is FLOAT"); + a.partial_cmp(&b).unwrap_or(Ordering::Equal) + }); + return Ok(()); + } + if type_id == TypeId::of::() { + array.sort_by(|a, b| { + let a = a + .read_lock::() + .expect("a is ImmutableString"); + let b = b + .read_lock::() + .expect("b is ImmutableString"); + a.as_str().cmp(b.as_str()) + }); + return Ok(()); + } + #[cfg(feature = "decimal")] + if type_id == TypeId::of::() { + array.sort_by(|a, b| { + let a = a.as_decimal().expect("a is Decimal"); + let b = b.as_decimal().expect("b is Decimal"); + a.cmp(&b) + }); + return Ok(()); + } + if type_id == TypeId::of::() { + array.sort_by(|a, b| { + let a = a.as_bool().expect("a is bool"); + let b = b.as_bool().expect("b is bool"); + a.cmp(&b) + }); + return Ok(()); + } + if type_id == TypeId::of::<()>() { + return Ok(()); + } + + Ok(()) + } + #[rhai_fn(return_raw, pure)] pub fn drain( ctx: NativeCallContext, array: &mut Array, filter: FnPtr, + ) -> Result> { + drain_with_fn_name(ctx, array, filter.fn_name()) + } + #[rhai_fn(name = "drain", return_raw)] + pub fn drain_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, ) -> Result> { if array.is_empty() { return Ok(Array::new()); } - let mut drained = Array::with_capacity(array.len()); + let mut index_val = Dynamic::UNIT; + let mut removed = Vec::with_capacity(array.len()); + let mut count = 0; - let mut i = 0; - let mut x = 0; + for (i, item) in array.iter_mut().enumerate() { + let mut args = [item, &mut index_val]; - while x < array.len() { - if filter - .call_dynamic(&ctx, None, [array[x].clone()]) - .or_else(|err| match *err { + let remove = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { + Ok(r) => r, + Err(err) => match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter.fn_name()) => + if fn_sig.starts_with(filter) => { - filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()]) + *args[1] = Dynamic::from(i as INT); + ctx.call_fn_raw(filter, true, false, &mut args)? } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "drain".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })? - .as_bool() - .unwrap_or(false) - { - drained.push(array.remove(x)); - } else { - x += 1; + _ => { + return Err(EvalAltResult::ErrorInFunctionCall( + "drain".to_string(), + ctx.source().unwrap_or("").to_string(), + err, + Position::NONE, + ) + .into()) + } + }, } + .as_bool() + .unwrap_or(false); - i += 1; + removed.push(remove); + + if remove { + count += 1; + } } - Ok(drained) + if count == 0 { + return Ok(Array::new()); + } + + let mut result = Vec::with_capacity(count); + let mut x = 0; + let mut i = 0; + + while i < array.len() { + if removed[x] { + result.push(array.remove(i)); + } else { + i += 1; + } + x += 1; + } + + Ok(result.into()) } #[rhai_fn(name = "drain")] pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array { @@ -790,52 +1006,79 @@ mod array_functions { array.drain(start..start + len).collect() } - #[rhai_fn(return_raw)] + #[rhai_fn(return_raw, pure)] pub fn retain( ctx: NativeCallContext, array: &mut Array, filter: FnPtr, + ) -> Result> { + retain_with_fn_name(ctx, array, filter.fn_name()) + } + #[rhai_fn(name = "retain", return_raw)] + pub fn retain_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, ) -> Result> { if array.is_empty() { return Ok(Array::new()); } - let mut drained = Array::new(); + let mut index_val = Dynamic::UNIT; + let mut removed = Vec::with_capacity(array.len()); + let mut count = 0; - let mut i = 0; - let mut x = 0; + for (i, item) in array.iter_mut().enumerate() { + let mut args = [item, &mut index_val]; - while x < array.len() { - if !filter - .call_dynamic(&ctx, None, [array[x].clone()]) - .or_else(|err| match *err { + let keep = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { + Ok(r) => r, + Err(err) => match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter.fn_name()) => + if fn_sig.starts_with(filter) => { - filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()]) + *args[1] = Dynamic::from(i as INT); + ctx.call_fn_raw(filter, true, false, &mut args)? } - _ => Err(err), - }) - .map_err(|err| { - Box::new(EvalAltResult::ErrorInFunctionCall( - "retain".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - )) - })? - .as_bool() - .unwrap_or(false) - { - drained.push(array.remove(x)); - } else { - x += 1; + _ => { + return Err(EvalAltResult::ErrorInFunctionCall( + "retain".to_string(), + ctx.source().unwrap_or("").to_string(), + err, + Position::NONE, + ) + .into()) + } + }, } + .as_bool() + .unwrap_or(false); - i += 1; + removed.push(!keep); + + if !keep { + count += 1; + } } - Ok(drained) + if count == 0 { + return Ok(Array::new()); + } + + let mut result = Vec::with_capacity(count); + let mut x = 0; + let mut i = 0; + + while i < array.len() { + if removed[x] { + result.push(array.remove(i)); + } else { + i += 1; + } + x += 1; + } + + Ok(result.into()) } #[rhai_fn(name = "retain")] pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array { @@ -884,7 +1127,7 @@ mod array_functions { for (a1, a2) in array1.iter_mut().zip(array2.iter_mut()) { if !ctx - .call_fn_dynamic_raw(OP_EQUALS, true, &mut [a1, a2]) + .call_fn_raw(OP_EQUALS, true, false, &mut [a1, a2]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _) if fn_sig.starts_with(OP_EQUALS) => diff --git a/src/packages/fn_basic.rs b/src/packages/fn_basic.rs index 4a92e1cc..a40c7b73 100644 --- a/src/packages/fn_basic.rs +++ b/src/packages/fn_basic.rs @@ -15,20 +15,16 @@ mod fn_ptr_functions { } #[cfg(not(feature = "no_function"))] - pub mod functions { - #[rhai_fn(name = "is_anonymous", get = "is_anonymous", pure)] - pub fn is_anonymous(fn_ptr: &mut FnPtr) -> bool { - fn_ptr.is_anonymous() - } + #[rhai_fn(name = "is_anonymous", get = "is_anonymous", pure)] + pub fn is_anonymous(fn_ptr: &mut FnPtr) -> bool { + fn_ptr.is_anonymous() } #[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_object"))] - pub mod functions_and_maps { - pub fn get_fn_metadata_list(ctx: NativeCallContext) -> crate::Array { - collect_fn_metadata(ctx) - } + pub fn get_fn_metadata_list(ctx: NativeCallContext) -> crate::Array { + collect_fn_metadata(ctx) } } diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index 65fb6484..c9f481d6 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -25,7 +25,7 @@ where #[cfg(not(feature = "unchecked"))] if let Some(r) = from.checked_add(&step) { if r == from { - return EvalAltResult::ErrorInFunctionCall( + return Err(EvalAltResult::ErrorInFunctionCall( "range".to_string(), Default::default(), EvalAltResult::ErrorArithmetic( @@ -35,7 +35,7 @@ where .into(), crate::Position::NONE, ) - .into(); + .into()); } } @@ -122,21 +122,27 @@ impl BitRange { #[cfg(not(feature = "unchecked"))] if offset >= BITS { - return EvalAltResult::ErrorBitFieldBounds(BITS, from, crate::Position::NONE) - .into(); + return Err( + EvalAltResult::ErrorBitFieldBounds(BITS, from, crate::Position::NONE).into(), + ); } offset } else { #[cfg(not(feature = "unchecked"))] if let Some(abs_from) = from.checked_abs() { if (abs_from as usize) > BITS { - return EvalAltResult::ErrorBitFieldBounds(BITS, from, crate::Position::NONE) - .into(); + return Err(EvalAltResult::ErrorBitFieldBounds( + BITS, + from, + crate::Position::NONE, + ) + .into()); } BITS - (abs_from as usize) } else { - return EvalAltResult::ErrorBitFieldBounds(BITS, from, crate::Position::NONE) - .into(); + return Err( + EvalAltResult::ErrorBitFieldBounds(BITS, from, crate::Position::NONE).into(), + ); } #[cfg(feature = "unchecked")] @@ -245,7 +251,7 @@ impl Iterator for CharsStream { } } - #[inline(always)] + #[inline] fn size_hint(&self) -> (usize, Option) { let remaining = self.0.len() - self.1; (remaining, Some(remaining)) @@ -255,7 +261,7 @@ impl Iterator for CharsStream { impl FusedIterator for CharsStream {} impl ExactSizeIterator for CharsStream { - #[inline(always)] + #[inline] fn len(&self) -> usize { self.0.len() - self.1 } @@ -325,10 +331,10 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, { pub fn new(from: FLOAT, to: FLOAT, step: FLOAT) -> Result> { #[cfg(not(feature = "unchecked"))] if step == 0.0 { - return EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), + return Err(EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), EvalAltResult::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE).into(), crate::Position::NONE, - ).into(); + ).into()); } Ok(Self(from, to, step)) @@ -387,10 +393,10 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, { pub fn new(from: Decimal, to: Decimal, step: Decimal) -> Result> { #[cfg(not(feature = "unchecked"))] if step.is_zero() { - return EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), + return Err(EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), EvalAltResult::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE).into(), crate::Position::NONE, - ).into(); + ).into()); } Ok(Self(from, to, step)) diff --git a/src/packages/lang_core.rs b/src/packages/lang_core.rs index 26d4c5b0..6c4c76a5 100644 --- a/src/packages/lang_core.rs +++ b/src/packages/lang_core.rs @@ -14,7 +14,7 @@ mod core_functions { #[rhai_fn(name = "set_tag", set = "tag", return_raw)] pub fn set_tag(value: &mut Dynamic, tag: INT) -> Result<(), Box> { if tag < Tag::MIN as INT { - EvalAltResult::ErrorArithmetic( + Err(EvalAltResult::ErrorArithmetic( format!( "{} is too small to fit into a tag (must be between {} and {})", tag, @@ -23,9 +23,9 @@ mod core_functions { ), Position::NONE, ) - .into() + .into()) } else if tag > Tag::MAX as INT { - EvalAltResult::ErrorArithmetic( + Err(EvalAltResult::ErrorArithmetic( format!( "{} is too large to fit into a tag (must be between {} and {})", tag, @@ -34,7 +34,7 @@ mod core_functions { ), Position::NONE, ) - .into() + .into()) } else { value.set_tag(tag as Tag); Ok(()) diff --git a/src/packages/logic.rs b/src/packages/logic.rs index a1fd8d8f..663b29d4 100644 --- a/src/packages/logic.rs +++ b/src/packages/logic.rs @@ -202,7 +202,7 @@ mod bit_field_functions { let offset = index as usize; if offset >= BITS { - EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into() + Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()) } else { Ok((value & (1 << offset)) != 0) } @@ -211,12 +211,12 @@ mod bit_field_functions { // Count from end if negative if offset > BITS { - EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into() + Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()) } else { Ok((value & (1 << (BITS - offset))) != 0) } } else { - EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into() + Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()) } } #[rhai_fn(return_raw)] @@ -225,7 +225,7 @@ mod bit_field_functions { let offset = index as usize; if offset >= BITS { - EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into() + Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()) } else { let mask = 1 << offset; if new_value { @@ -240,7 +240,7 @@ mod bit_field_functions { // Count from end if negative if offset > BITS { - EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into() + Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()) } else { let mask = 1 << offset; if new_value { @@ -251,7 +251,7 @@ mod bit_field_functions { Ok(()) } } else { - EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into() + Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()) } } #[rhai_fn(return_raw)] @@ -264,7 +264,7 @@ mod bit_field_functions { let offset = index as usize; if offset >= BITS { - return EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into(); + return Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()); } offset @@ -273,11 +273,11 @@ mod bit_field_functions { // Count from end if negative if offset > BITS { - return EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into(); + return Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()); } BITS - offset } else { - return EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into(); + return Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()); }; let bits = if offset + bits as usize > BITS { @@ -311,7 +311,7 @@ mod bit_field_functions { let offset = index as usize; if offset >= BITS { - return EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into(); + return Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()); } offset @@ -320,11 +320,11 @@ mod bit_field_functions { // Count from end if negative if offset > BITS { - return EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into(); + return Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()); } BITS - offset } else { - return EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into(); + return Err(EvalAltResult::ErrorBitFieldBounds(BITS, index, Position::NONE).into()); }; let bits = if offset + bits as usize > BITS { diff --git a/src/packages/map_basic.rs b/src/packages/map_basic.rs index b042d9e1..2b13c5d4 100644 --- a/src/packages/map_basic.rs +++ b/src/packages/map_basic.rs @@ -84,7 +84,7 @@ mod map_functions { for (m1, v1) in map1.iter_mut() { if let Some(v2) = map2.get_mut(m1) { let equals = ctx - .call_fn_dynamic_raw(OP_EQUALS, true, &mut [v1, v2]) + .call_fn_raw(OP_EQUALS, true, false, &mut [v1, v2]) .map(|v| v.as_bool().unwrap_or(false))?; if !equals { @@ -108,22 +108,21 @@ mod map_functions { } #[cfg(not(feature = "no_index"))] - pub mod indexing { - #[rhai_fn(pure)] - pub fn keys(map: &mut Map) -> Array { - if map.is_empty() { - Array::new() - } else { - map.keys().cloned().map(Into::::into).collect() - } + #[rhai_fn(pure)] + pub fn keys(map: &mut Map) -> Array { + if map.is_empty() { + Array::new() + } else { + map.keys().cloned().map(Into::::into).collect() } - #[rhai_fn(pure)] - pub fn values(map: &mut Map) -> Array { - if map.is_empty() { - Array::new() - } else { - map.values().cloned().collect() - } + } + #[cfg(not(feature = "no_index"))] + #[rhai_fn(pure)] + pub fn values(map: &mut Map) -> Array { + if map.is_empty() { + Array::new() + } else { + map.values().cloned().collect() } } } diff --git a/src/packages/math_basic.rs b/src/packages/math_basic.rs index 0f9f6a88..d008b8e4 100644 --- a/src/packages/math_basic.rs +++ b/src/packages/math_basic.rs @@ -114,11 +114,11 @@ mod int_functions { #[rhai_fn(name = "parse_int", return_raw)] pub fn parse_int_radix(string: &str, radix: INT) -> Result> { if !(2..=36).contains(&radix) { - return EvalAltResult::ErrorArithmetic( + return Err(EvalAltResult::ErrorArithmetic( format!("Invalid radix: '{}'", radix), Position::NONE, ) - .into(); + .into()); } INT::from_str_radix(string.trim(), radix as u32).map_err(|err| { @@ -261,11 +261,11 @@ mod float_functions { #[rhai_fn(name = "to_int", return_raw)] pub fn f32_to_int(x: f32) -> Result> { if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f32) { - EvalAltResult::ErrorArithmetic( + Err(EvalAltResult::ErrorArithmetic( format!("Integer overflow: to_int({})", x), Position::NONE, ) - .into() + .into()) } else { Ok(x.trunc() as INT) } @@ -273,11 +273,11 @@ mod float_functions { #[rhai_fn(name = "to_int", return_raw)] pub fn f64_to_int(x: f64) -> Result> { if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f64) { - EvalAltResult::ErrorArithmetic( + Err(EvalAltResult::ErrorArithmetic( format!("Integer overflow: to_int({})", x), Position::NONE, ) - .into() + .into()) } else { Ok(x.trunc() as INT) } @@ -293,11 +293,9 @@ mod float_functions { }) } #[cfg(not(feature = "f32_float"))] - pub mod f32_f64 { - #[rhai_fn(name = "to_float")] - pub fn f32_to_f64(x: f32) -> f64 { - x as f64 - } + #[rhai_fn(name = "to_float")] + pub fn f32_to_f64(x: f32) -> f64 { + x as f64 } } @@ -308,21 +306,23 @@ mod decimal_functions { prelude::{FromStr, RoundingStrategy}, Decimal, MathematicalOps, }; + #[cfg(not(feature = "no_float"))] + use std::convert::TryFrom; #[cfg(feature = "no_float")] - pub mod float_polyfills { - #[rhai_fn(name = "PI")] - pub fn pi() -> Decimal { - Decimal::PI - } - #[rhai_fn(name = "E")] - pub fn e() -> Decimal { - Decimal::E - } - #[rhai_fn(return_raw)] - pub fn parse_float(s: &str) -> Result> { - super::parse_decimal(s) - } + #[rhai_fn(name = "PI")] + pub fn pi() -> Decimal { + Decimal::PI + } + #[cfg(feature = "no_float")] + #[rhai_fn(name = "E")] + pub fn e() -> Decimal { + Decimal::E + } + #[cfg(feature = "no_float")] + #[rhai_fn(return_raw)] + pub fn parse_float(s: &str) -> Result> { + parse_decimal(s) } pub fn sin(x: Decimal) -> Decimal { @@ -480,39 +480,37 @@ mod decimal_functions { } #[cfg(not(feature = "no_float"))] - pub mod float { - use std::convert::TryFrom; - - #[rhai_fn(name = "to_decimal", return_raw)] - pub fn f32_to_decimal(x: f32) -> Result> { - Decimal::try_from(x).map_err(|_| { - EvalAltResult::ErrorArithmetic( - format!("Cannot convert to Decimal: to_decimal({})", x), - Position::NONE, - ) - .into() - }) - } - #[rhai_fn(name = "to_decimal", return_raw)] - pub fn f64_to_decimal(x: f64) -> Result> { - Decimal::try_from(x).map_err(|_| { - EvalAltResult::ErrorArithmetic( - format!("Cannot convert to Decimal: to_decimal({})", x), - Position::NONE, - ) - .into() - }) - } - #[rhai_fn(return_raw)] - pub fn to_float(x: Decimal) -> Result> { - FLOAT::try_from(x).map_err(|_| { - EvalAltResult::ErrorArithmetic( - format!("Cannot convert to floating-point: to_float({})", x), - Position::NONE, - ) - .into() - }) - } + #[rhai_fn(name = "to_decimal", return_raw)] + pub fn f32_to_decimal(x: f32) -> Result> { + Decimal::try_from(x).map_err(|_| { + EvalAltResult::ErrorArithmetic( + format!("Cannot convert to Decimal: to_decimal({})", x), + Position::NONE, + ) + .into() + }) + } + #[cfg(not(feature = "no_float"))] + #[rhai_fn(name = "to_decimal", return_raw)] + pub fn f64_to_decimal(x: f64) -> Result> { + Decimal::try_from(x).map_err(|_| { + EvalAltResult::ErrorArithmetic( + format!("Cannot convert to Decimal: to_decimal({})", x), + Position::NONE, + ) + .into() + }) + } + #[cfg(not(feature = "no_float"))] + #[rhai_fn(return_raw)] + pub fn to_float(x: Decimal) -> Result> { + FLOAT::try_from(x).map_err(|_| { + EvalAltResult::ErrorArithmetic( + format!("Cannot convert to floating-point: to_float({})", x), + Position::NONE, + ) + .into() + }) } } diff --git a/src/packages/string_basic.rs b/src/packages/string_basic.rs index 71a326a3..00aeee89 100644 --- a/src/packages/string_basic.rs +++ b/src/packages/string_basic.rs @@ -28,7 +28,7 @@ pub fn print_with_func( ctx: &NativeCallContext, value: &mut Dynamic, ) -> crate::ImmutableString { - match ctx.call_fn_dynamic_raw(fn_name, true, &mut [value]) { + match ctx.call_fn_raw(fn_name, true, false, &mut [value]) { Ok(result) if result.is::() => result .into_immutable_string() .expect("result is `ImmutableString`"), @@ -71,82 +71,73 @@ mod print_debug_functions { } #[cfg(not(feature = "no_float"))] - pub mod float_functions { - use crate::ast::FloatWrapper; - - #[rhai_fn(name = "print", name = "to_string")] - pub fn print_f64(number: f64) -> ImmutableString { - FloatWrapper::new(number).to_string().into() - } - #[rhai_fn(name = "print", name = "to_string")] - pub fn print_f32(number: f32) -> ImmutableString { - FloatWrapper::new(number).to_string().into() - } - #[rhai_fn(name = "debug", name = "to_debug")] - pub fn debug_f64(number: f64) -> ImmutableString { - format!("{:?}", FloatWrapper::new(number)).into() - } - #[rhai_fn(name = "debug", name = "to_debug")] - pub fn debug_f32(number: f32) -> ImmutableString { - format!("{:?}", FloatWrapper::new(number)).into() - } + #[rhai_fn(name = "print", name = "to_string")] + pub fn print_f64(number: f64) -> ImmutableString { + crate::ast::FloatWrapper::new(number).to_string().into() + } + #[cfg(not(feature = "no_float"))] + #[rhai_fn(name = "print", name = "to_string")] + pub fn print_f32(number: f32) -> ImmutableString { + crate::ast::FloatWrapper::new(number).to_string().into() + } + #[cfg(not(feature = "no_float"))] + #[rhai_fn(name = "debug", name = "to_debug")] + pub fn debug_f64(number: f64) -> ImmutableString { + format!("{:?}", crate::ast::FloatWrapper::new(number)).into() + } + #[cfg(not(feature = "no_float"))] + #[rhai_fn(name = "debug", name = "to_debug")] + pub fn debug_f32(number: f32) -> ImmutableString { + format!("{:?}", crate::ast::FloatWrapper::new(number)).into() } #[cfg(not(feature = "no_index"))] - pub mod array_functions { - use super::*; + #[rhai_fn( + name = "print", + name = "to_string", + name = "debug", + name = "to_debug", + pure + )] + pub fn format_array(ctx: NativeCallContext, array: &mut Array) -> ImmutableString { + let len = array.len(); + let mut result = String::with_capacity(len * 5 + 2); + result.push('['); - #[rhai_fn( - name = "print", - name = "to_string", - name = "debug", - name = "to_debug", - pure - )] - pub fn format_array(ctx: NativeCallContext, array: &mut Array) -> ImmutableString { - let len = array.len(); - let mut result = String::with_capacity(len * 5 + 2); - result.push('['); + array.iter_mut().enumerate().for_each(|(i, x)| { + result.push_str(&print_with_func(FUNC_TO_DEBUG, &ctx, x)); + if i < len - 1 { + result.push_str(", "); + } + }); - array.iter_mut().enumerate().for_each(|(i, x)| { - result.push_str(&print_with_func(FUNC_TO_DEBUG, &ctx, x)); - if i < len - 1 { - result.push_str(", "); - } - }); - - result.push(']'); - result.into() - } + result.push(']'); + result.into() } #[cfg(not(feature = "no_object"))] - pub mod map_functions { - use super::*; + #[rhai_fn( + name = "print", + name = "to_string", + name = "debug", + name = "to_debug", + pure + )] + pub fn format_map(ctx: NativeCallContext, map: &mut Map) -> ImmutableString { + let len = map.len(); + let mut result = String::with_capacity(len * 5 + 3); + result.push_str("#{"); - #[rhai_fn( - name = "print", - name = "to_string", - name = "debug", - name = "to_debug", - pure - )] - pub fn format_map(ctx: NativeCallContext, map: &mut Map) -> ImmutableString { - let len = map.len(); - let mut result = String::with_capacity(len * 5 + 3); - result.push_str("#{"); + map.iter_mut().enumerate().for_each(|(i, (k, v))| { + result.push_str(&format!( + "{:?}: {}{}", + k, + &print_with_func(FUNC_TO_DEBUG, &ctx, v), + if i < len - 1 { ", " } else { "" } + )); + }); - map.iter_mut().enumerate().for_each(|(i, (k, v))| { - result.push_str(&format!( - "{:?}: {}{}", - k, - &print_with_func(FUNC_TO_DEBUG, &ctx, v), - if i < len - 1 { ", " } else { "" } - )); - }); - - result.push('}'); - result.into() - } + result.push('}'); + result.into() } } diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index fb8d29e7..02955b09 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -471,11 +471,11 @@ mod string_functions { // Check if string will be over max size limit #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() { - return crate::EvalAltResult::ErrorDataTooLarge( + return Err(crate::EvalAltResult::ErrorDataTooLarge( "Length of string".to_string(), crate::Position::NONE, ) - .into(); + .into()); } let orig_len = string.chars().count(); @@ -490,11 +490,11 @@ mod string_functions { #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size() { - return crate::EvalAltResult::ErrorDataTooLarge( + return Err(crate::EvalAltResult::ErrorDataTooLarge( "Length of string".to_string(), crate::Position::NONE, ) - .into(); + .into()); } } @@ -516,11 +516,11 @@ mod string_functions { // Check if string will be over max size limit #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && len as usize > _ctx.engine().max_string_size() { - return crate::EvalAltResult::ErrorDataTooLarge( + return Err(crate::EvalAltResult::ErrorDataTooLarge( "Length of string".to_string(), crate::Position::NONE, ) - .into(); + .into()); } let mut str_len = string.chars().count(); @@ -542,11 +542,11 @@ mod string_functions { #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size() { - return crate::EvalAltResult::ErrorDataTooLarge( + return Err(crate::EvalAltResult::ErrorDataTooLarge( "Length of string".to_string(), crate::Position::NONE, ) - .into(); + .into()); } } diff --git a/src/parse.rs b/src/parse.rs index daa57566..e33d5c59 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -9,7 +9,6 @@ use crate::dynamic::AccessMode; use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS}; use crate::fn_hash::get_hasher; use crate::module::NamespaceRef; -use crate::optimize::{optimize_into_ast, OptimizationLevel}; use crate::token::{ is_keyword_function, is_valid_function_name, is_valid_identifier, Token, TokenStream, TokenizerControl, @@ -3219,8 +3218,9 @@ impl Engine { input: &mut TokenStream, state: &mut ParseState, scope: &Scope, - optimization_level: OptimizationLevel, + #[cfg(not(feature = "no_optimize"))] optimization_level: crate::OptimizationLevel, ) -> Result { + let _scope = scope; let mut functions = Default::default(); let settings = ParseSettings { @@ -3249,16 +3249,17 @@ impl Engine { let mut statements = StaticVec::new(); statements.push(Stmt::Expr(expr)); - Ok( - // Optimize AST - optimize_into_ast( - self, - scope, - statements, - Default::default(), - optimization_level, - ), - ) + #[cfg(not(feature = "no_optimize"))] + return Ok(crate::optimize::optimize_into_ast( + self, + _scope, + statements, + Default::default(), + optimization_level, + )); + + #[cfg(feature = "no_optimize")] + return Ok(AST::new(statements, crate::Module::new())); } /// Parse the global level statements. @@ -3322,19 +3323,40 @@ impl Engine { } /// Run the parser on an input stream, returning an AST. - #[inline(always)] + #[inline] pub(crate) fn parse( &self, input: &mut TokenStream, state: &mut ParseState, scope: &Scope, - optimization_level: OptimizationLevel, + #[cfg(not(feature = "no_optimize"))] optimization_level: crate::OptimizationLevel, ) -> Result { - let (statements, lib) = self.parse_global_level(input, state)?; + let _scope = scope; + let (statements, _lib) = self.parse_global_level(input, state)?; - Ok( - // Optimize AST - optimize_into_ast(self, scope, statements, lib, optimization_level), - ) + #[cfg(not(feature = "no_optimize"))] + return Ok(crate::optimize::optimize_into_ast( + self, + _scope, + statements, + _lib, + optimization_level, + )); + + #[cfg(feature = "no_optimize")] + #[cfg(not(feature = "no_function"))] + { + let mut m = crate::Module::new(); + + _lib.into_iter().for_each(|fn_def| { + m.set_script_fn(fn_def); + }); + + return Ok(AST::new(statements, m)); + } + + #[cfg(feature = "no_optimize")] + #[cfg(feature = "no_function")] + return Ok(AST::new(statements, crate::Module::new())); } } diff --git a/src/scope.rs b/src/scope.rs index 028287a5..6f217481 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -482,7 +482,7 @@ impl<'a> Scope<'a> { /// # Panics /// /// Panics if the index is out of bounds. - #[inline(always)] + #[inline] #[must_use] pub(crate) fn get_mut_by_index(&mut self, index: usize) -> &mut Dynamic { self.values.get_mut(index).expect("index is out of bounds") @@ -565,7 +565,7 @@ impl<'a> Scope<'a> { /// assert!(is_constant); /// assert_eq!(value.cast::(), "hello"); /// ``` - #[inline(always)] + #[inline] pub fn iter(&self) -> impl Iterator { self.iter_raw() .map(|(name, constant, value)| (name, constant, value.flatten_clone())) @@ -582,7 +582,7 @@ impl<'a> Scope<'a> { } impl<'a, K: Into>> Extend<(K, Dynamic)> for Scope<'a> { - #[inline(always)] + #[inline] fn extend>(&mut self, iter: T) { iter.into_iter().for_each(|(name, value)| { self.names.push((name.into(), Default::default())); diff --git a/src/serde/de.rs b/src/serde/de.rs index 3dfc2548..b7c3e67a 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -38,12 +38,12 @@ impl<'de> DynamicDeserializer<'de> { } /// Shortcut for a type conversion error. fn type_error_str(&self, error: &str) -> Result> { - EvalAltResult::ErrorMismatchOutputType( + Err(EvalAltResult::ErrorMismatchOutputType( error.into(), self.value.type_name().into(), Position::NONE, ) - .into() + .into()) } fn deserialize_int>( &mut self, diff --git a/src/serde/ser.rs b/src/serde/ser.rs index f42253dc..bfd0d128 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -313,24 +313,24 @@ impl Serializer for &mut DynamicSerializer { make_variant(_variant, content) } #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } fn serialize_seq(self, _len: Option) -> Result> { #[cfg(not(feature = "no_index"))] return Ok(DynamicSerializer::new(Array::new().into())); #[cfg(feature = "no_index")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "arrays are not supported with 'no_index'".into(), Position::NONE, ) - .into(); + .into()); } fn serialize_tuple(self, len: usize) -> Result> { @@ -359,24 +359,24 @@ impl Serializer for &mut DynamicSerializer { array: Array::with_capacity(_len), }); #[cfg(any(feature = "no_object", feature = "no_index"))] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "tuples are not supported with 'no_index' or 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } fn serialize_map(self, _len: Option) -> Result> { #[cfg(not(feature = "no_object"))] return Ok(DynamicSerializer::new(Map::new().into())); #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } fn serialize_struct( @@ -400,12 +400,12 @@ impl Serializer for &mut DynamicSerializer { map: Default::default(), }); #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } } @@ -425,12 +425,12 @@ impl SerializeSeq for DynamicSerializer { Ok(()) } #[cfg(feature = "no_index")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "arrays are not supported with 'no_index'".into(), Position::NONE, ) - .into(); + .into()); } // Close the sequence. @@ -438,12 +438,12 @@ impl SerializeSeq for DynamicSerializer { #[cfg(not(feature = "no_index"))] return Ok(self._value); #[cfg(feature = "no_index")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "arrays are not supported with 'no_index'".into(), Position::NONE, ) - .into(); + .into()); } } @@ -463,24 +463,24 @@ impl SerializeTuple for DynamicSerializer { Ok(()) } #[cfg(feature = "no_index")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "tuples are not supported with 'no_index'".into(), Position::NONE, ) - .into(); + .into()); } fn end(self) -> Result> { #[cfg(not(feature = "no_index"))] return Ok(self._value); #[cfg(feature = "no_index")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "tuples are not supported with 'no_index'".into(), Position::NONE, ) - .into(); + .into()); } } @@ -500,24 +500,24 @@ impl SerializeTupleStruct for DynamicSerializer { Ok(()) } #[cfg(feature = "no_index")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "tuples are not supported with 'no_index'".into(), Position::NONE, ) - .into(); + .into()); } fn end(self) -> Result> { #[cfg(not(feature = "no_index"))] return Ok(self._value); #[cfg(feature = "no_index")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "tuples are not supported with 'no_index'".into(), Position::NONE, ) - .into(); + .into()); } } @@ -532,12 +532,12 @@ impl SerializeMap for DynamicSerializer { Ok(()) } #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } fn serialize_value( @@ -561,12 +561,12 @@ impl SerializeMap for DynamicSerializer { Ok(()) } #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } fn serialize_entry( @@ -586,24 +586,24 @@ impl SerializeMap for DynamicSerializer { Ok(()) } #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } fn end(self) -> Result> { #[cfg(not(feature = "no_object"))] return Ok(self._value); #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } } @@ -624,24 +624,24 @@ impl SerializeStruct for DynamicSerializer { Ok(()) } #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } fn end(self) -> Result> { #[cfg(not(feature = "no_object"))] return Ok(self._value); #[cfg(feature = "no_object")] - return EvalAltResult::ErrorMismatchDataType( + return Err(EvalAltResult::ErrorMismatchDataType( "".into(), "object maps are not supported with 'no_object'".into(), Position::NONE, ) - .into(); + .into()); } } diff --git a/src/serde/str.rs b/src/serde/str.rs index 81e90f8b..1ad17537 100644 --- a/src/serde/str.rs +++ b/src/serde/str.rs @@ -19,12 +19,12 @@ impl<'a> StringSliceDeserializer<'a> { } /// Shortcut for a type conversion error. fn type_error(&self) -> Result> { - EvalAltResult::ErrorMismatchOutputType( + Err(EvalAltResult::ErrorMismatchOutputType( type_name::().into(), "string".into(), Position::NONE, ) - .into() + .into()) } } diff --git a/src/token.rs b/src/token.rs index 1ffef163..5266b467 100644 --- a/src/token.rs +++ b/src/token.rs @@ -113,7 +113,7 @@ impl Position { /// If `line` is zero, then [`None`] is returned. /// /// If `position` is zero, then it is at the beginning of a line. - #[inline(always)] + #[inline] #[must_use] pub const fn new_const(line: u16, position: u16) -> Option { if line == 0 { @@ -129,7 +129,7 @@ impl Position { }) } /// Get the line number (1-based), or [`None`] if there is no position. - #[inline(always)] + #[inline] #[must_use] pub const fn line(self) -> Option { #[cfg(not(feature = "no_position"))] @@ -143,7 +143,7 @@ impl Position { return None; } /// Get the character position (1-based), or [`None`] if at beginning of a line. - #[inline(always)] + #[inline] #[must_use] pub const fn position(self) -> Option { #[cfg(not(feature = "no_position"))] @@ -157,7 +157,7 @@ impl Position { return None; } /// Advance by one character position. - #[inline(always)] + #[inline] pub(crate) fn advance(&mut self) { #[cfg(not(feature = "no_position"))] { @@ -174,7 +174,7 @@ impl Position { /// # Panics /// /// Panics if already at beginning of a line - cannot rewind to a previous line. - #[inline(always)] + #[inline] pub(crate) fn rewind(&mut self) { #[cfg(not(feature = "no_position"))] { @@ -184,7 +184,7 @@ impl Position { } } /// Advance to the next line. - #[inline(always)] + #[inline] pub(crate) fn new_line(&mut self) { #[cfg(not(feature = "no_position"))] { @@ -198,7 +198,7 @@ impl Position { } } /// Is this [`Position`] at the beginning of a line? - #[inline(always)] + #[inline] #[must_use] pub const fn is_beginning_of_line(self) -> bool { #[cfg(not(feature = "no_position"))] @@ -207,7 +207,7 @@ impl Position { return false; } /// Is there no [`Position`]? - #[inline(always)] + #[inline] #[must_use] pub const fn is_none(self) -> bool { #[cfg(not(feature = "no_position"))] @@ -216,7 +216,7 @@ impl Position { return true; } /// Print this [`Position`] for debug purposes. - #[inline(always)] + #[inline] pub(crate) fn debug_print(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { #[cfg(not(feature = "no_position"))] if !self.is_none() { @@ -1352,7 +1352,7 @@ fn is_numeric_digit(c: char) -> bool { /// Test if the comment block is a doc-comment. #[cfg(not(feature = "no_function"))] #[cfg(feature = "metadata")] -#[inline(always)] +#[inline] #[must_use] pub fn is_doc_comment(comment: &str) -> bool { (comment.starts_with("///") && !comment.starts_with("////")) diff --git a/src/unsafe.rs b/src/unsafe.rs index a6fe76f8..3ce5b4c9 100644 --- a/src/unsafe.rs +++ b/src/unsafe.rs @@ -8,7 +8,7 @@ use std::{ }; /// Cast a type into another type. -#[inline(always)] +#[inline] pub fn unsafe_try_cast(a: A) -> Result { if TypeId::of::() == a.type_id() { // SAFETY: Just checked we have the right type. We explicitly forget the @@ -25,7 +25,7 @@ pub fn unsafe_try_cast(a: A) -> Result { } /// Cast a Boxed type into another type. -#[inline(always)] +#[inline] pub fn unsafe_cast_box(item: Box) -> Result, Box> { // Only allow casting to the exact same type if TypeId::of::() == TypeId::of::() { diff --git a/tests/call_fn.rs b/tests/call_fn.rs index a239e4a5..f57b61bc 100644 --- a/tests/call_fn.rs +++ b/tests/call_fn.rs @@ -1,5 +1,5 @@ #![cfg(not(feature = "no_function"))] -use rhai::{Dynamic, Engine, EvalAltResult, FnPtr, Func, FuncArgs, Scope, INT}; +use rhai::{Dynamic, Engine, EvalAltResult, FnPtr, Func, FuncArgs, Scope, AST, INT}; use std::{any::TypeId, iter::once}; #[test] @@ -225,3 +225,88 @@ fn test_anonymous_fn() -> Result<(), Box> { Ok(()) } + +#[test] +fn test_call_fn_events() -> Result<(), Box> { + // Event handler + struct Handler { + // Scripting engine + pub engine: Engine, + // Use a custom 'Scope' to keep stored state + pub scope: Scope<'static>, + // Program script + pub ast: AST, + } + + const SCRIPT: &str = r#" + fn start(data) { 42 + data } + fn end(data) { 0 } + "#; + + impl Handler { + pub fn new() -> Self { + let engine = Engine::new(); + + // Create a custom 'Scope' to hold state + let mut scope = Scope::new(); + + // Add initialized state into the custom 'Scope' + scope.push("state", false); + + // Compile the handler script. + let ast = engine.compile(SCRIPT).unwrap(); + + // Evaluate the script to initialize it and other state variables. + // In a real application you'd again be handling errors... + engine.run_ast_with_scope(&mut scope, &ast).unwrap(); + + // The event handler is essentially these three items: + Handler { engine, scope, ast } + } + + // Say there are three events: 'start', 'end', 'update'. + // In a real application you'd be handling errors... + pub fn on_event(&mut self, event_name: &str, event_data: INT) -> Dynamic { + let engine = &self.engine; + let scope = &mut self.scope; + let ast = &self.ast; + + match event_name { + // The 'start' event maps to function 'start'. + // In a real application you'd be handling errors... + "start" => engine.call_fn(scope, ast, "start", (event_data,)).unwrap(), + + // The 'end' event maps to function 'end'. + // In a real application you'd be handling errors... + "end" => engine.call_fn(scope, ast, "end", (event_data,)).unwrap(), + + // The 'update' event maps to function 'update'. + // This event provides a default implementation when the scripted function is not found. + "update" => engine + .call_fn(scope, ast, "update", (event_data,)) + .or_else(|err| match *err { + EvalAltResult::ErrorFunctionNotFound(fn_name, _) + if fn_name.starts_with("update") => + { + // Default implementation of 'update' event handler + self.scope.set_value("state", true); + // Turn function-not-found into a success + Ok(Dynamic::UNIT) + } + _ => Err(err), + }) + .unwrap(), + // In a real application you'd be handling unknown events... + _ => panic!("unknown event: {}", event_name), + } + } + } + + let mut handler = Handler::new(); + assert!(!handler.scope.get_value::("state").unwrap()); + handler.on_event("update", 999); + assert!(handler.scope.get_value::("state").unwrap()); + assert_eq!(handler.on_event("start", 999).as_int().unwrap(), 1041); + + Ok(()) +} diff --git a/tests/stack.rs b/tests/stack.rs index 527522bf..febdcbbd 100644 --- a/tests/stack.rs +++ b/tests/stack.rs @@ -46,13 +46,39 @@ fn test_stack_overflow_parsing() -> Result<(), Box> { ParseErrorType::ExprTooDeep ); + engine.compile("1 + 2")?; + + #[cfg(debug_assertions)] + engine.compile( + " + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + ", + )?; + + #[cfg(debug_assertions)] + assert_eq!( + *engine + .compile( + " + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + + 1 + " + ) + .expect_err("should error") + .0, + ParseErrorType::ExprTooDeep + ); + engine.set_max_expr_depths( 100, #[cfg(not(feature = "no_function"))] 6, ); - engine.compile("1 + 2")?; engine.compile( " 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 +