diff --git a/CHANGELOG.md b/CHANGELOG.md index b953235b..11d4a28b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Bug fixes * Parsing of index expressions is relaxed and many cases no longer result in an index-type error to allow for custom indexers. * Merging or combining a self-contained `AST` into another `AST` now works properly. * Plugin modules/functions no longer generate errors under `#![deny(missing_docs)]`. +* Calling a property on a function call that returns a shared value no longer causes an error. Deprecated API's ---------------- diff --git a/src/eval/chaining.rs b/src/eval/chaining.rs index 2d9899c5..a5426ca1 100644 --- a/src/eval/chaining.rs +++ b/src/eval/chaining.rs @@ -652,7 +652,9 @@ impl Engine { _ if is_assignment => unreachable!("cannot assign to an expression"), // {expr}.??? or {expr}[???] expr => { - let value = self.eval_expr(scope, global, caches, lib, this_ptr, expr, level)?; + let value = self + .eval_expr(scope, global, caches, lib, this_ptr, expr, level)? + .flatten(); let obj_ptr = &mut value.into(); let root = ("", expr.start_position()); self.eval_dot_index_chain_helper( @@ -1043,6 +1045,11 @@ impl Engine { }) } + #[cfg(not(feature = "no_closure"))] + Dynamic(Union::Shared(..)) => { + unreachable!("`get_indexed_mut` cannot handle shared values") + } + _ if use_indexers => self .call_indexer_get(global, caches, lib, target, &mut idx, level) .map(Into::into), diff --git a/tests/closures.rs b/tests/closures.rs index 36ae9e33..f7c1b291 100644 --- a/tests/closures.rs +++ b/tests/closures.rs @@ -1,5 +1,5 @@ #![cfg(not(feature = "no_function"))] -use rhai::{Engine, EvalAltResult, FnPtr, ParseErrorType, Scope, INT}; +use rhai::{Dynamic, Engine, EvalAltResult, FnPtr, ParseErrorType, Scope, INT}; use std::any::TypeId; use std::cell::RefCell; use std::mem::take; @@ -217,6 +217,34 @@ fn test_closures_sharing() -> Result<(), Box> { 6 ); + #[cfg(not(feature = "no_object"))] + { + let mut m = Map::new(); + m.insert("hello".into(), "world".into()); + let m = Dynamic::from(m).into_shared(); + + engine.register_fn("baz", move || m.clone()); + + assert!(!engine.eval::( + " + let m = baz(); + m.is_shared() + " + )?); + + assert_eq!( + engine.eval::( + " + let m = baz(); + m.hello + " + )?, + "world" + ); + + assert_eq!(engine.eval::("baz().hello")?, "world"); + } + Ok(()) }