Skip to content

Sketch block scope push permanently retains its enclosing stack frame #13550

Description

@jtran

Both executors give a sketch block's body its own environment whose parent is the current environment, via a snapshot: the recursive executor in Node<SketchBlock>::get_result (exec_ast.rs, snapshot + push_new_env_for_call), the machine in sketch_block_body_setup (machine.rs). snapshot() sets might_be_refed on the parent environment, the flag is never cleared, and Environment::compact() skips any env with the flag set. So the frame enclosing a sketch block is retained with all its bindings for the life of the program, even when nothing escaped the block.

Impact today is low: sketch blocks almost always appear at a module's top level, where the parent is the root/module environment, which is retained anyway. It becomes a real per-call leak if sketch blocks inside functions become common (each call's parameters and locals would be retained).

Fix: replace the snapshot() + push_new_env_for_call(snapshot) pattern in both executors' sketch-block setup (Node<SketchBlock>::get_result in exec_ast.rs, sketch_block_body_setup in machine.rs) with push_new_env_for_block, which defers marking the parent until the block's environment is itself referenced (added for KCL 3.0 if-arm scoping in #13535). Note this applies to both environments the sketch block pushes — the sketch-alias env created via prep_mem's snapshot and the body env. Both are popped through the arena's common pop path, so the deferred pin applies automatically once the pushes are swapped. Verify sketch-mode re-execution still works: cached environment refs held across runs (SketchModeState) must mark the envs referenced for the deferred pin to keep their parent chains alive. A regression test should assert, via the arena's test-only envs_with_bindings, that repeated calls to a function containing a sketch block with no escaping references don't accumulate retained frames.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions