Skip to content

fix(interpreter): assert_no_streams_in_env should descend into closure bodies #115

@humancto

Description

@humancto

Background

PR #114 added Interpreter::assert_no_streams_in_env (debug builds only) which walks the template env at fork time and panics if it finds a Value::Stream. The walker correctly recurses into containers (Array/Tuple/Set/Map/Object/Result/Some/Frozen) but uses _ => {} to skip Value::Function and Value::Lambda bodies.

That comment in the code said "closure scopes are walked separately by deep_clone_isolated" -- but those two walks have different purposes. deep_clone_isolated walks for Arc-dedup and closure isolation; the Stream-detection walker is checking for a runtime invariant. A Stream value reachable only via a captured closure escapes the assert.

Example pattern:

let inner = (fn() {
    let s = stream([1,2,3])
    return fn() { s.next() }
})()

inner is a Lambda whose closure captures s: Value::Stream. Pre-PR-#114 this was an invisible footgun; post-PR it's still an invisible footgun because the assert doesn't descend into closure bodies.

What to add

Have the walker also descend into Value::Function::closure and Value::Lambda::closure (locking the Lambda's Arc and walking its scopes), with a scope_map-style cycle break to avoid re-walking shared scopes.

~30 lines, one extra micro-allocation per fork.

Origin: rust-expert review on PR #114, follow-up #1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions