Skip to content

Advance the world at skipped :latestworld statements - #171

Merged
aviatesk merged 1 commit into
masterfrom
avi/skip-latestworld
Oct 3, 2026
Merged

aviatesk merged 1 commit into
masterfrom
avi/skip-latestworld

Conversation

@aviatesk

@aviatesk aviatesk commented Oct 3, 2026

Copy link
Copy Markdown
Member

Since Julia 1.12, top-level code advances its world only at :latestworld statements, and JuliaInterpreter is going to follow that instead of moving top-level frames to the latest world before every statement (JuliaDebug/JuliaInterpreter.jl#783). Selective evaluation skips the statements it does not select, :latestworld ones included, so later statements could then read bindings in a world prior to their definition, or fail to call methods defined earlier in the thunk.

next_or_nothing! now advances the world of the frame when it skips a :latestworld statement. This covers selective_eval! and the callers that skip statements themselves with next_or_nothing!, such as Revise. It is compatible with current JuliaInterpreter versions, whose top-level frames are always in the latest world anyway.

Selecting the :latestworld statements in lines_required! instead would grow the slice: a selected statement pulls in its control flow and type definition, so branch conditions, loop iterations, and struct definitions that the slice does not need would get evaluated. Advancing the world while skipping has no effect on the program state, and matches native execution, which advances the world at every :latestworld it reaches.

Since Julia 1.12, top-level code advances its world only at `:latestworld`
statements, and JuliaInterpreter is going to follow that instead of moving
top-level frames to the latest world before every statement. Selective
evaluation skips the statements it does not select, `:latestworld` ones
included, so later statements could then read bindings in a world prior to
their definition, or fail to call methods defined earlier in the thunk.

`next_or_nothing!` now advances the world of the frame when it skips a
`:latestworld` statement. This covers `selective_eval!` and the callers that
skip statements themselves with `next_or_nothing!`, such as Revise. It is
compatible with current JuliaInterpreter versions, whose top-level frames
are always in the latest world anyway.

Selecting the `:latestworld` statements in `lines_required!` instead would
grow the slice: a selected statement pulls in its control flow and type
definition, so branch conditions, loop iterations, and struct definitions
that the slice does not need would get evaluated. Advancing the world while
skipping has no effect on the program state, and matches native execution,
which advances the world at every `:latestworld` it reaches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aviatesk
aviatesk merged commit b1d5e4d into master Oct 3, 2026
11 checks passed
@aviatesk
aviatesk deleted the avi/skip-latestworld branch October 3, 2026 12:46
aviatesk added a commit to timholy/Revise.jl that referenced this pull request Oct 3, 2026
….2 (#1150)

JuliaInterpreter 0.12 interprets the code passed to `Core.eval`, and on
Julia 1.12 and later its top-level frames advance their world only at
`:latestworld` statements, as native evaluation does. Neither changes
what Revise does:
- Revise evaluates top-level code with `Compiled()` and handles
  `Core.eval` itself in `methods_by_execution!`, so the recursive
  interpretation of `Core.eval` does not apply to it.
- Revise skips the statements it does not select with
  `LoweredCodeUtils.next_or_nothing!`, which advances the world at
  skipped `:latestworld` statements since LoweredCodeUtils 3.10
  (JuliaDebug/LoweredCodeUtils.jl#171), the first version that allows
  JuliaInterpreter 0.12.

The patch release is needed for JET, which requires JuliaInterpreter
0.12 and whose test environment includes Revise: Revise 3.17.1 and
earlier cap JuliaInterpreter at 0.11, so JET cannot move to 0.12 until a
Revise release allows it.
aviatesk added a commit to timholy/Revise.jl that referenced this pull request Oct 3, 2026
#1150 required JuliaInterpreter 0.12, but Revise works
with both 0.11 and 0.12 without changes. Requiring 0.12 would hold
Revise back at 3.17.1 in every environment that pins JuliaInterpreter to
0.11, e.g. one that also has Debugger.jl, which does not allow 0.12
yet, so those environments would miss later Revise releases.

The compat now allows both again, and the LoweredCodeUtils bound goes
back to 3.7. With JuliaInterpreter 0.12 the resolver still picks
LoweredCodeUtils 3.10 or later, because earlier versions cap
JuliaInterpreter at 0.11, and 3.10 advances the world at the
`:latestworld` statements that Revise skips
(JuliaDebug/LoweredCodeUtils.jl#171). With JuliaInterpreter 0.11,
Revise runs with the same packages as 3.17.1.
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