Fix bug with capturing undefined variable.

This commit is contained in:
Stephen Chung 2022-07-29 09:43:40 +08:00
parent ea38185cac
commit fc976172e7
3 changed files with 22 additions and 7 deletions

View File

@ -11,6 +11,7 @@ Bug fixes
* `switch` cases with conditions that evaluate to constant `()` no longer optimize to `false` (should raise a type error during runtime). * `switch` cases with conditions that evaluate to constant `()` no longer optimize to `false` (should raise a type error during runtime).
* Fixes concatenation of BLOB's and strings, where the BLOB's should be interpreted as UTF-8 encoded strings. * Fixes concatenation of BLOB's and strings, where the BLOB's should be interpreted as UTF-8 encoded strings.
* Capturing an unknown variable in a closure no longer panics.
New features New features
------------ ------------

View File

@ -1016,7 +1016,7 @@ impl Engine {
// Share statement // Share statement
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Stmt::Share(name, ..) => { Stmt::Share(name, pos) => {
if let Some((index, ..)) = scope.get_index(name) { if let Some((index, ..)) = scope.get_index(name) {
let val = scope.get_mut_by_index(index); let val = scope.get_mut_by_index(index);
@ -1024,10 +1024,10 @@ impl Engine {
// Replace the variable with a shared value. // Replace the variable with a shared value.
*val = std::mem::take(val).into_shared(); *val = std::mem::take(val).into_shared();
} }
Ok(Dynamic::UNIT)
} else { } else {
unreachable!("variable {} not found for sharing", name); Err(ERR::ErrorVariableNotFound(name.to_string(), *pos).into())
} }
Ok(Dynamic::UNIT)
} }
_ => unreachable!("statement cannot be evaluated: {:?}", stmt), _ => unreachable!("statement cannot be evaluated: {:?}", stmt),

View File

@ -42,21 +42,35 @@ fn test_fn_ptr_curry_call() -> Result<(), Box<EvalAltResult>> {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
fn test_closures() -> Result<(), Box<EvalAltResult>> { fn test_closures() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new(); let mut engine = Engine::new();
let mut scope = Scope::new();
scope.push("x", 42 as INT);
assert!(matches!( assert!(matches!(
*engine engine
.compile_expression("let f = |x| {};") .compile_expression("|x| {}")
.expect_err("should error") .expect_err("should error")
.0, .err_type(),
ParseErrorType::BadInput(..) ParseErrorType::BadInput(..)
)); ));
assert_eq!(
engine.eval_with_scope::<INT>(
&mut scope,
"
let f = || { x };
f.call()
",
)?,
42
);
assert_eq!( assert_eq!(
engine.eval::<INT>( engine.eval::<INT>(
" "
let foo = #{ x: 42 }; let foo = #{ x: 42 };
let f = || { this.x }; let f = || { this.x };
foo.call(f) foo.call(f)
", ",
)?, )?,
42 42