diff --git a/CHANGELOG.md b/CHANGELOG.md index 6523076d..85615fb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Bug fixes * Panic when passing a shared string into a registered function as `&str` argument is fixed. * Panic when calling `switch` statements on custom types is fixed. * Potential overflow panics in `range(from, to, step)` is fixed. +* `&mut String` parameters in registered functions no longer panic when passed a string. * Some expressions involving shared variables now work properly, for example `x in shared_value`, `return shared_value`, `obj.field = shared_value` etc. Previously, the resultant value is still shared which is counter-intuitive. * Errors in native Rust functions now contain the correct function call positions. * Fixed error types in `EvalAltResult::ErrorMismatchDataType` which were swapped. diff --git a/src/fn_register.rs b/src/fn_register.rs index 74ca32be..5751f0d3 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -161,15 +161,15 @@ pub fn map_result(data: RhaiResult) -> RhaiResult { /// Remap `&str` | `String` to `ImmutableString`. #[inline(always)] -fn map_type_id() -> TypeId { - let id = TypeId::of::(); +fn map_type_id() -> TypeId { + let ref_id = TypeId::of::(); - if id == TypeId::of::<&str>() { + if ref_id == TypeId::of::<&str>() { TypeId::of::() - } else if id == TypeId::of::() { + } else if ref_id == TypeId::of::() { TypeId::of::() } else { - id + TypeId::of::() } } @@ -193,7 +193,7 @@ macro_rules! def_register { #[inline(always)] fn register_fn(&mut self, name: &str, f: FN) -> &mut Self { self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, - &[$(map_type_id::<$par>()),*], + &[$(map_type_id::<$param, $par>()),*], CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $let => $clone => $arg),*)) ); self @@ -208,7 +208,7 @@ macro_rules! def_register { #[inline(always)] fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self { self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, - &[$(map_type_id::<$par>()),*], + &[$(map_type_id::<$param, $par>()),*], CallableFunction::$abi(make_func!(f : map_result ; $($par => $let => $clone => $arg),*)) ); self diff --git a/tests/string.rs b/tests/string.rs index a5328fad..0db10eb0 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -64,6 +64,25 @@ fn test_string_dynamic() -> Result<(), Box> { Ok(()) } +#[test] +fn test_string_mut() -> Result<(), Box> { + let mut engine = Engine::new(); + + engine.register_fn("foo", |x: INT, s: &str| s.len() as INT + x); + engine.register_fn("bar", |x: INT, s: String| s.len() as INT + x); + engine.register_fn("baz", |s: &mut String| s.len()); + + assert_eq!(engine.eval::(r#"foo(1, "hello")"#)?, 6); + assert_eq!(engine.eval::(r#"bar(1, "hello")"#)?, 6); + assert!( + matches!(*engine.eval::(r#"baz("hello")"#).expect_err("should error"), + EvalAltResult::ErrorFunctionNotFound(f, _) if f == "baz (&str | ImmutableString | String)" + ) + ); + + Ok(()) +} + #[cfg(not(feature = "no_object"))] #[test] fn test_string_substring() -> Result<(), Box> {