World age delay doesn't occur with `@eval` in `begin` or `let` blocks, but does with `eval`

World age is expected to produce a delay between a method or Task’s compiled code and their changes to the global state, but it wasn’t clear to me what happens in top-level begin or let blocks. Weirdly, there’s this discrepancy between eval and @eval, and I still don’t know whether these blocks are supposed to commit to a specific world age or not. I haven’t exhaustively wrote versions for all blocks in Julia, but it also applies to for and while.

julia> const pi = 3 # v1.12.2
3

julia> begin
       println(pi)
       const pi = 3.1 # possible here without manual eval
       println(pi) # updated
       end;
3
3.1

julia> begin
       println(pi)
       @eval const pi = 3.14
       println(pi) # updated
       end;
3.1
3.14

julia> begin
       println(pi)
       eval(:(const pi = 3.141))
       println(pi) # obsolete
       end;
3.14
3.14

julia> let
       println(pi)
       @eval const pi = 3.1415
       println(pi) # updated
       end;
3.141
3.1415

julia> let
       println(pi)
       eval(:(const pi = 3.14159))
       println(pi) # obsolete
       end;
3.1415
3.1415

The first tls_world_age example in the Manual page also changes to show the local world age incrementing if Core.eval is changed to @eval.

julia> function f end
f (generic function with 0 methods)

julia> begin
       @show (Int(Base.get_world_counter()), Int(Base.tls_world_age()))
       @eval @__MODULE__() f() = 1
       @show (Int(Base.get_world_counter()), Int(Base.tls_world_age()))
       f()
       end
(Int(Base.get_world_counter()), Int(Base.tls_world_age())) = (38693, 38693)
(Int(Base.get_world_counter()), Int(Base.tls_world_age())) = (38694, 38694)
1

@eval inserts an explicit world age increment:

julia> @macroexpand @eval x = 1
:(let var"#1#eval_local_result" = Core.eval(Main, $(Expr(:copyast, :($(QuoteNode(:(x = 1)))))))
      $(Expr(Symbol("latestworld-if-toplevel")))
      var"#1#eval_local_result"
  end)

The function version can’t because it’s not syntax.

1 Like