Background
PR #114 added 5 unit tests for Environment::deep_clone_isolated. All five exercise either:
Value::Lambda (which always goes through the full closure path), or
- top-level
fn (which hits the is_global_fn fast path in call_function_inner and bypasses the closure entirely).
The interesting middle case -- a named inner function returned from another function -- produces a Value::Function with closure.scopes.len() > 1 and does exercise the deep_clone_isolated Function branch. Currently untested.
What to add
Direct test:
#[test]
fn fork_for_serving_isolates_non_global_function_closure() {
let mut template = Interpreter::new();
template.run_repl(...
// fn outer() { let mut x = 0; fn inner() { x = x + 1 }; return inner }
// let bump = outer()
...).expect("setup");
let mut a = template.fork_for_serving();
let mut b = template.fork_for_serving();
// bump in fork a is a Value::Function with closure.scopes.len() > 1
// calling it should mutate fork a's `x`, not template's, not b's
}
Branch is implemented and almost certainly correct (parallel to Lambda) but the gap should be closed.
Origin: rust-expert review on PR #114, follow-up #2.
Background
PR #114 added 5 unit tests for
Environment::deep_clone_isolated. All five exercise either:Value::Lambda(which always goes through the full closure path), orfn(which hits theis_global_fnfast path incall_function_innerand bypasses the closure entirely).The interesting middle case -- a named inner function returned from another function -- produces a
Value::Functionwithclosure.scopes.len() > 1and does exercise thedeep_clone_isolatedFunction branch. Currently untested.What to add
Direct test:
Branch is implemented and almost certainly correct (parallel to Lambda) but the gap should be closed.
Origin: rust-expert review on PR #114, follow-up #2.