From a704d2698661269a1c0256352dccca87734532dd Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 14 Mar 2022 08:26:27 +0800 Subject: [PATCH 1/7] Fixup ArgBackup. --- src/func/call.rs | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/src/func/call.rs b/src/func/call.rs index 2dc1b952..67778783 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -37,6 +37,7 @@ struct ArgBackup<'a> { impl<'a> ArgBackup<'a> { /// Create a new `ArgBackup`. + #[inline(always)] pub fn new() -> Self { Self { orig_mut: None, @@ -60,8 +61,8 @@ impl<'a> ArgBackup<'a> { /// # Panics /// /// Panics when `args` is empty. - #[inline] - fn change_first_arg_to_copy(&mut self, args: &mut FnCallArgs<'a>) { + #[inline(always)] + pub fn change_first_arg_to_copy(&mut self, args: &mut FnCallArgs<'a>) { // Clone the original value. self.value_copy = args[0].clone(); @@ -86,7 +87,7 @@ impl<'a> ArgBackup<'a> { /// If `change_first_arg_to_copy` has been called, this function **MUST** be called _BEFORE_ /// exiting the current scope. Otherwise it is undefined behavior as the shorter lifetime will leak. #[inline(always)] - fn restore_first_arg(mut self, args: &mut FnCallArgs<'a>) { + pub fn restore_first_arg(mut self, args: &mut FnCallArgs<'a>) { if let Some(p) = self.orig_mut.take() { args[0] = p; } @@ -94,7 +95,7 @@ impl<'a> ArgBackup<'a> { } impl Drop for ArgBackup<'_> { - #[inline] + #[inline(always)] fn drop(&mut self) { // Panic if the shorter lifetime leaks. assert!( @@ -382,15 +383,12 @@ impl Engine { let mut _result = if let Some(FnResolutionCacheEntry { func, source }) = func { assert!(func.is_native()); + let mut backup = ArgBackup::new(); + // Calling pure function but the first argument is a reference? - let mut backup: Option = None; if is_ref_mut && func.is_pure() && !args.is_empty() { // Clone the first argument - backup = Some(ArgBackup::new()); - backup - .as_mut() - .expect("`Some`") - .change_first_arg_to_copy(args); + backup.change_first_arg_to_copy(args); } let source = match (source.as_str(), parent_source.as_str()) { @@ -420,9 +418,7 @@ impl Engine { }; // Restore the original reference - if let Some(bk) = backup { - bk.restore_first_arg(args) - } + backup.restore_first_arg(args); result } else { @@ -711,7 +707,7 @@ impl Engine { // Method call of script function - map first argument to `this` let (first_arg, rest_args) = args.split_first_mut().unwrap(); - let result = self.call_script_fn( + self.call_script_fn( scope, global, state, @@ -722,19 +718,14 @@ impl Engine { true, pos, level, - ); - - result? + ) } else { // Normal call of script function + let mut backup = ArgBackup::new(); + // The first argument is a reference? - let mut backup: Option = None; if is_ref_mut && !args.is_empty() { - backup = Some(ArgBackup::new()); - backup - .as_mut() - .expect("`Some`") - .change_first_arg_to_copy(args); + backup.change_first_arg_to_copy(args); } let result = self.call_script_fn( @@ -742,17 +733,15 @@ impl Engine { ); // Restore the original reference - if let Some(bk) = backup { - bk.restore_first_arg(args) - } + backup.restore_first_arg(args); - result? + result }; // Restore the original source mem::swap(&mut global.source, &mut source); - return Ok((result, false)); + return Ok((result?, false)); } // Native function call From 672cda63ab358d5d02626244d5601252106e39d8 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 14 Mar 2022 08:50:17 +0800 Subject: [PATCH 2/7] Simplify formatting. --- src/api/call_fn.rs | 8 +--- src/api/eval.rs | 8 +--- src/api/type_names.rs | 4 +- src/func/call.rs | 99 +++++++++++++++++-------------------------- src/func/native.rs | 8 +--- src/optimizer.rs | 3 +- src/types/fn_ptr.rs | 16 ++----- 7 files changed, 53 insertions(+), 93 deletions(-) diff --git a/src/api/call_fn.rs b/src/api/call_fn.rs index 32b91c96..80a0d193 100644 --- a/src/api/call_fn.rs +++ b/src/api/call_fn.rs @@ -69,12 +69,8 @@ impl Engine { let typ = self.map_type_name(result.type_name()); result.try_cast().ok_or_else(|| { - ERR::ErrorMismatchOutputType( - self.map_type_name(type_name::()).into(), - typ.into(), - Position::NONE, - ) - .into() + let t = self.map_type_name(type_name::()).into(); + ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into() }) } /// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments and the diff --git a/src/api/eval.rs b/src/api/eval.rs index fc7d1bd7..dc4a4336 100644 --- a/src/api/eval.rs +++ b/src/api/eval.rs @@ -195,12 +195,8 @@ impl Engine { let typ = self.map_type_name(result.type_name()); result.try_cast::().ok_or_else(|| { - ERR::ErrorMismatchOutputType( - self.map_type_name(type_name::()).into(), - typ.into(), - Position::NONE, - ) - .into() + let t = self.map_type_name(type_name::()).into(); + ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into() }) } /// Evaluate an [`AST`] with own scope. diff --git a/src/api/type_names.rs b/src/api/type_names.rs index faf1fa44..3edb1c3b 100644 --- a/src/api/type_names.rs +++ b/src/api/type_names.rs @@ -125,7 +125,7 @@ impl Engine { #[inline(never)] #[must_use] pub(crate) fn make_type_mismatch_err(&self, typ: &str, pos: Position) -> RhaiError { - ERR::ErrorMismatchDataType(self.map_type_name(type_name::()).into(), typ.into(), pos) - .into() + let t = self.map_type_name(type_name::()).into(); + ERR::ErrorMismatchDataType(t, typ.into(), pos).into() } } diff --git a/src/func/call.rs b/src/func/call.rs index 67778783..5d88059c 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -466,11 +466,8 @@ impl Engine { KEYWORD_PRINT => { if let Some(ref print) = self.print { let text = result.into_immutable_string().map_err(|typ| { - ERR::ErrorMismatchOutputType( - self.map_type_name(type_name::()).into(), - typ.into(), - pos, - ) + let t = self.map_type_name(type_name::()).into(); + ERR::ErrorMismatchOutputType(t, typ.into(), pos) })?; (print(&text).into(), false) } else { @@ -480,11 +477,8 @@ impl Engine { KEYWORD_DEBUG => { if let Some(ref debug) = self.debug { let text = result.into_immutable_string().map_err(|typ| { - ERR::ErrorMismatchOutputType( - self.map_type_name(type_name::()).into(), - typ.into(), - pos, - ) + let t = self.map_type_name(type_name::()).into(); + ERR::ErrorMismatchOutputType(t, typ.into(), pos) })?; let source = match global.source.as_str() { "" => None, @@ -507,15 +501,10 @@ impl Engine { crate::engine::FN_IDX_GET => { assert!(args.len() == 2); - Err(ERR::ErrorIndexingType( - format!( - "{} [{}]", - self.map_type_name(args[0].type_name()), - self.map_type_name(args[1].type_name()) - ), - pos, - ) - .into()) + let t0 = self.map_type_name(args[0].type_name()); + let t1 = self.map_type_name(args[1].type_name()); + + Err(ERR::ErrorIndexingType(format!("{} [{}]", t0, t1), pos).into()) } // index setter function not found? @@ -523,16 +512,11 @@ impl Engine { crate::engine::FN_IDX_SET => { assert!(args.len() == 3); - Err(ERR::ErrorIndexingType( - format!( - "{} [{}] = {}", - self.map_type_name(args[0].type_name()), - self.map_type_name(args[1].type_name()), - self.map_type_name(args[2].type_name()) - ), - pos, - ) - .into()) + let t0 = self.map_type_name(args[0].type_name()); + let t1 = self.map_type_name(args[1].type_name()); + let t2 = self.map_type_name(args[3].type_name()); + + Err(ERR::ErrorIndexingType(format!("{} [{}] = {}", t0, t1, t2), pos).into()) } // Getter function not found? @@ -540,11 +524,13 @@ impl Engine { _ if name.starts_with(crate::engine::FN_GET) => { assert!(args.len() == 1); + let prop = &name[crate::engine::FN_GET.len()..]; + let t0 = self.map_type_name(args[0].type_name()); + Err(ERR::ErrorDotExpr( format!( "Unknown property '{}' - a getter is not registered for type '{}'", - &name[crate::engine::FN_GET.len()..], - self.map_type_name(args[0].type_name()) + prop, t0 ), pos, ) @@ -556,12 +542,14 @@ impl Engine { _ if name.starts_with(crate::engine::FN_SET) => { assert!(args.len() == 2); + let prop = &name[crate::engine::FN_SET.len()..]; + let t0 = self.map_type_name(args[0].type_name()); + let t1 = self.map_type_name(args[1].type_name()); + Err(ERR::ErrorDotExpr( format!( "No writable property '{}' - a setter is not registered for type '{}' to handle '{}'", - &name[crate::engine::FN_SET.len()..], - self.map_type_name(args[0].type_name()), - self.map_type_name(args[1].type_name()), + prop, t0, t1 ), pos, ) @@ -608,8 +596,11 @@ impl Engine { level: usize, ) -> RhaiResultOf<(Dynamic, bool)> { fn no_method_err(name: &str, pos: Position) -> RhaiResultOf<(Dynamic, bool)> { - let msg = format!("'{0}' should not be called this way. Try {0}(...);", name); - Err(ERR::ErrorRuntime(msg.into(), pos).into()) + Err(ERR::ErrorRuntime( + (format!("'{0}' should not be called this way. Try {0}(...);", name)).into(), + pos, + ) + .into()) } // Check for data race. @@ -623,10 +614,8 @@ impl Engine { match fn_name { // Handle type_of() KEYWORD_TYPE_OF if args.len() == 1 => { - return Ok(( - self.map_type_name(args[0].type_name()).to_string().into(), - false, - )) + let typ = self.map_type_name(args[0].type_name()).to_string().into(); + return Ok((typ, false)); } // Handle is_def_fn() @@ -816,16 +805,12 @@ impl Engine { KEYWORD_FN_PTR_CALL => { if !call_args.is_empty() { if !call_args[0].is::() { - return Err(self.make_type_mismatch_err::( - self.map_type_name(call_args[0].type_name()), - *call_arg_pos, - )); + let typ = self.map_type_name(call_args[0].type_name()); + return Err(self.make_type_mismatch_err::(typ, *call_arg_pos)); } } else { - return Err(self.make_type_mismatch_err::( - self.map_type_name(target.type_name()), - pos, - )); + let typ = self.map_type_name(target.type_name()); + return Err(self.make_type_mismatch_err::(typ, pos)); } // FnPtr call on object @@ -855,10 +840,8 @@ impl Engine { } KEYWORD_FN_PTR_CURRY => { if !target.is::() { - return Err(self.make_type_mismatch_err::( - self.map_type_name(target.type_name()), - pos, - )); + let typ = self.map_type_name(target.type_name()); + return Err(self.make_type_mismatch_err::(typ, pos)); } let fn_ptr = target.read_lock::().expect("`FnPtr`"); @@ -1005,10 +988,8 @@ impl Engine { self.get_arg_value(scope, global, state, lib, this_ptr, arg, level)?; if !arg_value.is::() { - return Err(self.make_type_mismatch_err::( - self.map_type_name(arg_value.type_name()), - arg_pos, - )); + let typ = self.map_type_name(arg_value.type_name()); + return Err(self.make_type_mismatch_err::(typ, arg_pos)); } let fn_ptr = arg_value.cast::(); @@ -1055,10 +1036,8 @@ impl Engine { self.get_arg_value(scope, global, state, lib, this_ptr, first, level)?; if !arg_value.is::() { - return Err(self.make_type_mismatch_err::( - self.map_type_name(arg_value.type_name()), - arg_pos, - )); + let typ = self.map_type_name(arg_value.type_name()); + return Err(self.make_type_mismatch_err::(typ, arg_pos)); } let (name, fn_curry) = arg_value.cast::().take_data(); diff --git a/src/func/native.rs b/src/func/native.rs index c3932824..91756290 100644 --- a/src/func/native.rs +++ b/src/func/native.rs @@ -277,12 +277,8 @@ impl<'a> NativeCallContext<'a> { let typ = self.engine().map_type_name(result.type_name()); result.try_cast().ok_or_else(|| { - ERR::ErrorMismatchOutputType( - self.engine().map_type_name(type_name::()).into(), - typ.into(), - Position::NONE, - ) - .into() + let t = self.engine().map_type_name(type_name::()).into(); + ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into() }) } /// Call a function inside the call context. diff --git a/src/optimizer.rs b/src/optimizer.rs index a8fa2e4c..a9952ce0 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -1085,7 +1085,8 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) { match x.name.as_str() { KEYWORD_TYPE_OF if arg_values.len() == 1 => { state.set_dirty(); - *expr = Expr::from_dynamic(state.engine.map_type_name(arg_values[0].type_name()).into(), *pos); + let typ = state.engine.map_type_name(arg_values[0].type_name()).into(); + *expr = Expr::from_dynamic(typ, *pos); return; } #[cfg(not(feature = "no_closure"))] diff --git a/src/types/fn_ptr.rs b/src/types/fn_ptr.rs index 08712902..9d2d60cf 100644 --- a/src/types/fn_ptr.rs +++ b/src/types/fn_ptr.rs @@ -162,12 +162,8 @@ impl FnPtr { let typ = engine.map_type_name(result.type_name()); result.try_cast().ok_or_else(|| { - ERR::ErrorMismatchOutputType( - engine.map_type_name(type_name::()).into(), - typ.into(), - Position::NONE, - ) - .into() + let t = engine.map_type_name(type_name::()).into(); + ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into() }) } /// Call the function pointer with curried arguments (if any). @@ -190,12 +186,8 @@ impl FnPtr { let typ = context.engine().map_type_name(result.type_name()); result.try_cast().ok_or_else(|| { - ERR::ErrorMismatchOutputType( - context.engine().map_type_name(type_name::()).into(), - typ.into(), - Position::NONE, - ) - .into() + let t = context.engine().map_type_name(type_name::()).into(); + ERR::ErrorMismatchOutputType(t, typ.into(), Position::NONE).into() }) } /// Call the function pointer with curried arguments (if any). From a4fbb297409be3683855149aa35597f32633f8eb Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 14 Mar 2022 09:34:28 +0800 Subject: [PATCH 3/7] Add .gitattributes. --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..98bce048 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.rhai linguist-language=JavaScript From 63716759bedc91303d8d2e41d50aa5b57abf13f3 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 14 Mar 2022 11:28:52 +0800 Subject: [PATCH 4/7] Fix typo. --- src/func/call.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/func/call.rs b/src/func/call.rs index 5d88059c..1a5e9960 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -514,7 +514,7 @@ impl Engine { let t0 = self.map_type_name(args[0].type_name()); let t1 = self.map_type_name(args[1].type_name()); - let t2 = self.map_type_name(args[3].type_name()); + let t2 = self.map_type_name(args[2].type_name()); Err(ERR::ErrorIndexingType(format!("{} [{}] = {}", t0, t1, t2), pos).into()) } From 6223e1a6f17a769651dc51c5a229559ad05c2903 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 14 Mar 2022 12:04:24 +0800 Subject: [PATCH 5/7] Fix test output. --- codegen/ui_tests/export_fn_raw_return.stderr | 4 ++-- codegen/ui_tests/export_mod_raw_return.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/codegen/ui_tests/export_fn_raw_return.stderr b/codegen/ui_tests/export_fn_raw_return.stderr index 094b6756..576e999f 100644 --- a/codegen/ui_tests/export_fn_raw_return.stderr +++ b/codegen/ui_tests/export_fn_raw_return.stderr @@ -1,8 +1,8 @@ -error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied +error[E0599]: `bool` is not an iterator --> 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 + | ^^^^ `bool` is not an iterator | = note: the following trait bounds were not satisfied: `bool: std::iter::Iterator` diff --git a/codegen/ui_tests/export_mod_raw_return.stderr b/codegen/ui_tests/export_mod_raw_return.stderr index 93ad1364..55e1d185 100644 --- a/codegen/ui_tests/export_mod_raw_return.stderr +++ b/codegen/ui_tests/export_mod_raw_return.stderr @@ -1,8 +1,8 @@ -error[E0599]: the method `map` exists for type `bool`, but its trait bounds were not satisfied +error[E0599]: `bool` is not an iterator --> 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 + | ^^^^ `bool` is not an iterator | = note: the following trait bounds were not satisfied: `bool: std::iter::Iterator` From dc8c4ed8f41e66f9483598250d9ea00a30f6db3b Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 17 Mar 2022 17:00:48 +0800 Subject: [PATCH 6/7] Improve string functions. --- src/func/native.rs | 10 +++++++++- src/packages/string_more.rs | 32 +++++++++++++++++++++++--------- src/types/immutable_string.rs | 10 +++++++++- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/func/native.rs b/src/func/native.rs index 91756290..d3e1e3a7 100644 --- a/src/func/native.rs +++ b/src/func/native.rs @@ -344,7 +344,7 @@ impl<'a> NativeCallContext<'a> { } } -/// Consume a [`Shared`] resource and return a mutable reference to the wrapped value. +/// Return a mutable reference to the wrapped value of a [`Shared`] resource. /// If the resource is shared (i.e. has other outstanding references), a cloned copy is used. #[inline(always)] #[must_use] @@ -353,6 +353,14 @@ pub fn shared_make_mut(value: &mut Shared) -> &mut T { Shared::make_mut(value) } +/// Return a mutable reference to the wrapped value of a [`Shared`] resource. +#[inline(always)] +#[must_use] +#[allow(dead_code)] +pub fn shared_get_mut(value: &mut Shared) -> Option<&mut T> { + Shared::get_mut(value) +} + /// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise. #[inline] #[must_use] diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 79e392c9..182ee743 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -193,7 +193,11 @@ mod string_functions { /// Clear the string, making it empty. pub fn clear(string: &mut ImmutableString) { if !string.is_empty() { - string.make_mut().clear(); + if let Some(s) = string.get_mut() { + s.clear(); + } else { + *string = ImmutableString::new(); + } } } /// Cut off the string at the specified number of characters. @@ -220,8 +224,8 @@ mod string_functions { let copy = string.make_mut(); copy.clear(); copy.extend(chars.into_iter().take(len as usize)); - } else if !string.is_empty() { - string.make_mut().clear(); + } else { + clear(string); } } /// Remove whitespace characters from both ends of the string. @@ -231,13 +235,23 @@ mod string_functions { /// ```rhai /// let text = " hello "; /// - /// print(text.trim()); // prints "hello" + /// text.trim(); + /// + /// print(text); // prints "hello" /// ``` pub fn trim(string: &mut ImmutableString) { - let trimmed = string.trim(); + if let Some(s) = string.get_mut() { + let trimmed = s.trim(); - if trimmed.len() < string.len() { - *string = trimmed.to_string().into(); + if trimmed != s { + *s = trimmed.into(); + } + } else { + let trimmed = string.trim(); + + if trimmed != string { + *string = trimmed.into(); + } } } /// Remove the last character from the string and return it. @@ -313,7 +327,7 @@ mod string_functions { /// ``` #[rhai_fn(pure)] pub fn to_upper(string: &mut ImmutableString) -> ImmutableString { - if string.is_empty() || string.chars().all(char::is_uppercase) { + if string.chars().all(char::is_uppercase) { string.clone() } else { string.to_uppercase().into() @@ -366,7 +380,7 @@ mod string_functions { /// print(text); // prints "hello, world!"; /// ``` pub fn make_lower(string: &mut ImmutableString) { - if !string.is_empty() && string.chars().any(|ch| !ch.is_lowercase()) { + if string.chars().any(|ch| !ch.is_lowercase()) { *string = string.to_lowercase().into(); } } diff --git a/src/types/immutable_string.rs b/src/types/immutable_string.rs index 1df41b4d..e959b83c 100644 --- a/src/types/immutable_string.rs +++ b/src/types/immutable_string.rs @@ -1,6 +1,6 @@ //! The `ImmutableString` type. -use crate::func::native::{shared_make_mut, shared_take}; +use crate::func::native::{shared_get_mut, shared_make_mut, shared_take}; use crate::{Shared, SmartString}; #[cfg(feature = "no_std")] use std::prelude::v1::*; @@ -580,6 +580,7 @@ impl ImmutableString { Self(SmartString::new_const().into()) } /// Consume the [`ImmutableString`] and convert it into a [`String`]. + /// /// If there are other references to the same string, a cloned copy is returned. #[inline] pub fn into_owned(mut self) -> String { @@ -588,10 +589,17 @@ impl ImmutableString { } /// Make sure that the [`ImmutableString`] is unique (i.e. no other outstanding references). /// Then return a mutable reference to the [`SmartString`]. + /// + /// If there are other references to the same string, a cloned copy is used. #[inline(always)] pub(crate) fn make_mut(&mut self) -> &mut SmartString { shared_make_mut(&mut self.0) } + /// Return a mutable reference to the [`SmartString`] wrapped by the [`ImmutableString`]. + #[inline(always)] + pub(crate) fn get_mut(&mut self) -> Option<&mut SmartString> { + shared_get_mut(&mut self.0) + } /// Returns `true` if the two [`ImmutableString`]'s point to the same allocation. /// /// # Example From d01a6d428f0f770668848f86c83aa77047ba3875 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 18 Mar 2022 17:11:52 +0800 Subject: [PATCH 7/7] Fix tests. --- codegen/src/module.rs | 2 +- codegen/ui_tests/non_clonable.stderr | 3 +++ codegen/ui_tests/non_clonable_second.stderr | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/codegen/src/module.rs b/codegen/src/module.rs index eaa43070..c25a102d 100644 --- a/codegen/src/module.rs +++ b/codegen/src/module.rs @@ -264,7 +264,7 @@ 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 = sub_modules - .drain(..) + .into_iter() .try_fold::<_, _, Result<_, syn::Error>>(Vec::new(), |mut acc, m| { acc.push(m.generate_inner()?); Ok(acc) diff --git a/codegen/ui_tests/non_clonable.stderr b/codegen/ui_tests/non_clonable.stderr index cb0e05d1..8a8fc1f1 100644 --- a/codegen/ui_tests/non_clonable.stderr +++ b/codegen/ui_tests/non_clonable.stderr @@ -1,6 +1,8 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied --> ui_tests/non_clonable.rs:11:23 | +10 | #[export_fn] + | ------------ in this procedural macro expansion 11 | pub fn test_fn(input: NonClonable) -> bool { | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` | @@ -9,3 +11,4 @@ note: required by a bound in `rhai::Dynamic::cast` | | pub fn cast(self) -> T { | ^^^^^ required by this bound in `rhai::Dynamic::cast` + = note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/codegen/ui_tests/non_clonable_second.stderr b/codegen/ui_tests/non_clonable_second.stderr index 359a145c..413c3a70 100644 --- a/codegen/ui_tests/non_clonable_second.stderr +++ b/codegen/ui_tests/non_clonable_second.stderr @@ -1,6 +1,8 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied --> ui_tests/non_clonable_second.rs:11:27 | +10 | #[export_fn] + | ------------ in this procedural macro expansion 11 | pub fn test_fn(a: u32, b: NonClonable) -> bool { | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` | @@ -9,3 +11,4 @@ note: required by a bound in `rhai::Dynamic::cast` | | pub fn cast(self) -> T { | ^^^^^ required by this bound in `rhai::Dynamic::cast` + = note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info)