Skip to content

Require the :leaves and :pop_exceptions of required EnterNodes - #172

Merged
aviatesk merged 1 commit into
masterfrom
avi/require-handler-exits
Oct 11, 2026
Merged

aviatesk merged 1 commit into
masterfrom
avi/require-handler-exits

Conversation

@aviatesk

Copy link
Copy Markdown
Member

lines_required! selects an EnterNode through add_control_flow! when its try block contains required statements, but nothing selects the :leaves exiting it, since add_ssa_preds! follows them only backward to the EnterNode. The selective evaluation then stays in the exception handler, and in the dynamic scope of the EnterNode if any, for the rest of the frame. For example, requiring both assignments below evaluates outside to 1 instead of 0:

Base.ScopedValues.@with sv => 1 begin
    global inside = sv[]
end
global outside = sv[]

Likewise, an error thrown after a try block is caught by the handler left entered, which runs the statements after the try block again.

This change adds the add_handler_exits! step, which requires the :leaves and :pop_exceptions referencing a required EnterNode, so that the selective evaluation exits its handler and scope, and restores the exception stack after its catch block.

On Julia 1.10, :leaves count the handlers to exit instead of referencing the :enters, so only the :pop_exceptions are required there. Callers with their own selection loops, e.g. JET and TestRunner, need to call add_handler_exits! to get this fix as well.

`lines_required!` selects an `EnterNode` through `add_control_flow!`
when its `try` block contains required statements, but nothing selects
the `:leave`s exiting it, since `add_ssa_preds!` follows them only
backward to the `EnterNode`. The selective evaluation then stays in
the exception handler, and in the dynamic scope of the `EnterNode` if
any, for the rest of the frame. For example, requiring both
assignments below evaluates `outside` to `1` instead of `0`:

    Base.ScopedValues.@with sv => 1 begin
        global inside = sv[]
    end
    global outside = sv[]

Likewise, an error thrown after a `try` block is caught by the handler
left entered, which runs the statements after the `try` block again.

This change adds the `add_handler_exits!` step, which requires the
`:leave`s and `:pop_exception`s referencing a required `EnterNode`, so
that the selective evaluation exits its handler and scope, and
restores the exception stack after its `catch` block.

On Julia 1.10, `:leave`s count the handlers to exit instead of
referencing the `:enter`s, so only the `:pop_exception`s are required
there. Callers with their own selection loops, e.g. JET and
TestRunner, need to call `add_handler_exits!` to get this fix as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aviatesk
aviatesk merged commit 25c209b into master Oct 11, 2026
11 checks passed
@aviatesk
aviatesk deleted the avi/require-handler-exits branch October 11, 2026 04:15
aviatesk added a commit to aviatesk/JET.jl that referenced this pull request Oct 11, 2026
The statement selection for top-level concretization could select an
`EnterNode`, e.g. of a `try` or `@with` block containing definitions,
for the control flow without the `:leave`s exiting it. The code
concretized after the block then ran within the block's exception
handler and dynamic scope:

    sv = Base.ScopedValues.ScopedValue(0)
    Base.ScopedValues.@with sv => 1 begin
        global inside() = 1
    end
    @eval outside() = $(sv[]) # defined `outside()` returning `1`

An error thrown by such code was also caught by the handler left
entered, so the code after the block ran again.

`select_dependencies!` now calls `LoweredCodeUtils.add_handler_exits!`,
which selects the `:leave`s and `:pop_exception`s of the selected
`EnterNode`s. Since it was added in LoweredCodeUtils 3.10.1
(JuliaDebug/LoweredCodeUtils.jl#172), this change bumps the
LoweredCodeUtils compat accordingly. The new test in
`test/toplevel/test_virtualprocess.jl` covers the example above.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant