diff --git a/src/api/optimize.rs b/src/api/optimize.rs index 7589c2fd..fca162f2 100644 --- a/src/api/optimize.rs +++ b/src/api/optimize.rs @@ -56,12 +56,7 @@ impl Engine { .shared_lib() .iter_fn() .filter(|f| f.func.is_script()) - .map(|f| { - f.func - .get_script_fn_def() - .expect("script-defined function") - .clone() - }) + .map(|f| f.func.get_script_fn_def().unwrap().clone()) .collect(); crate::optimizer::optimize_into_ast( diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index b05a01a3..b5171d8e 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -146,7 +146,7 @@ impl Engine { let target_is_shared = false; if target_is_shared { - lock_guard = target.write_lock::().expect("`Dynamic`"); + lock_guard = target.write_lock::().unwrap(); lhs_ptr_inner = &mut *lock_guard; } else { lhs_ptr_inner = &mut *target; @@ -181,7 +181,20 @@ impl Engine { } } else { // Normal assignment - *target.as_mut() = new_val; + + #[cfg(not(feature = "no_closure"))] + if target.is_shared() { + // Handle case where target is a `Dynamic` shared value + // (returned by a variable resolver, for example) + *target.write_lock::().unwrap() = new_val; + } else { + *target.as_mut() = new_val; + } + + #[cfg(feature = "no_closure")] + { + *target.as_mut() = new_val; + } } target.propagate_changed_value(op_info.pos) @@ -251,8 +264,8 @@ impl Engine { let var_name = lhs.get_variable_name(false).expect("`Expr::Variable`"); #[cfg(not(feature = "no_closure"))] - // Temp results from expressions are flattened so should never be shared. - // A shared value may be provided by a variable resolver, however. + // Also handle case where target is a `Dynamic` shared value + // (returned by a variable resolver, for example) let is_temp_result = !lhs_ptr.is_ref() && !lhs_ptr.is_shared(); #[cfg(feature = "no_closure")] let is_temp_result = !lhs_ptr.is_ref(); diff --git a/src/optimizer.rs b/src/optimizer.rs index 7d4498af..89fae709 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -578,7 +578,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // Then check ranges if value.is::() && !ranges.is_empty() { - let value = value.as_int().expect("`INT`"); + let value = value.as_int().unwrap(); // Only one range or all ranges without conditions if ranges.len() == 1 diff --git a/src/tokenizer.rs b/src/tokenizer.rs index bce10ea4..59a63bb5 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1520,7 +1520,7 @@ fn get_next_token_inner( } #[cfg(any(not(feature = "no_float"), feature = "decimal"))] '.' => { - stream.get_next().expect("`.`"); + stream.get_next().unwrap(); // Check if followed by digits or something that cannot start a property name match stream.peek_next().unwrap_or('\0') { @@ -1567,7 +1567,7 @@ fn get_next_token_inner( '+' | '-' => { result.push(next_char); pos.advance(); - result.push(stream.get_next().expect("`+` or `-`")); + result.push(stream.get_next().unwrap()); pos.advance(); } // Not a floating-point number diff --git a/tests/var_scope.rs b/tests/var_scope.rs index 5c6cc29c..fdf256d3 100644 --- a/tests/var_scope.rs +++ b/tests/var_scope.rs @@ -196,13 +196,14 @@ fn test_var_resolver() -> Result<(), Box> { #[cfg(not(feature = "no_closure"))] { - assert_eq!(engine.eval_with_scope::(&mut scope, "HELLO")?, 1); + assert_eq!(engine.eval::("HELLO")?, 1); *base.write_lock::().unwrap() = 42; - assert_eq!(engine.eval_with_scope::(&mut scope, "HELLO")?, 42); - assert_eq!( - engine.eval_with_scope::(&mut scope, "HELLO = HELLO * 2; HELLO")?, - 84 - ); + assert_eq!(engine.eval::("HELLO")?, 42); + engine.run("HELLO = 123")?; + assert_eq!(base.as_int().unwrap(), 123); + assert_eq!(engine.eval::("HELLO = HELLO + 1; HELLO")?, 124); + assert_eq!(engine.eval::("HELLO = HELLO * 2; HELLO")?, 248); + assert_eq!(base.as_int().unwrap(), 248); } assert_eq!(engine.eval_with_scope::(&mut scope, "chameleon")?, 1);