Skip to content

Commit 518a90c

Browse files
authored
evaluate_methoddef: add @invokelatest to avoid world age error (#697)
It appears that when executing `:jl_method_def` in edge cases using `baremodule`, world age errors may occur. Adding `@invokelatest` avoids this issue. For details, please refer to the test case.
1 parent b429971 commit 518a90c

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

src/interpret.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ function eval_rhs(interp::Interpreter, frame::Frame, node::Expr)
409409
head === :aliasscope || head === :popaliasscope
410410
return nothing
411411
elseif head === :method && length(node.args) == 1
412-
return evaluate_methoddef(interp, frame, node)
412+
return @invokelatest evaluate_methoddef(interp, frame, node)
413413
end
414414
return lookup_expr(interp, frame, node)
415415
end
@@ -514,7 +514,7 @@ function step_expr!(interp::Interpreter, frame::Frame, @nospecialize(node), isto
514514
# (https://github.com/JuliaDebug/JuliaInterpreter.jl/issues/591)
515515
elseif istoplevel
516516
if node.head === :method && length(node.args) > 1
517-
rhs = evaluate_methoddef(interp, frame, node)
517+
rhs = @invokelatest evaluate_methoddef(interp, frame, node)
518518
elseif node.head === :module
519519
error("this should have been handled by split_expressions")
520520
elseif node.head === :using || node.head === :import || node.head === :export

test/toplevel.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,3 +649,24 @@ let ex = quote import Test end
649649
JuliaInterpreter.finish_and_return!(Frame(ImportTest, ex), true)
650650
@test @invokelatest JuliaInterpreter.isdefinedglobal(ImportTest, :Test)
651651
end
652+
653+
module BareModuleTest end
654+
function toplevel_eval(m, x)
655+
modexs = ExprSplitter(m, x)
656+
for (mod, ex) in modexs
657+
frame = Frame(mod, ex)
658+
while true
659+
JuliaInterpreter.through_methoddef_or_done!(frame) === nothing && break
660+
end
661+
end
662+
end
663+
let ex = :(baremodule BareModule
664+
using Base
665+
function foo(x::Cint)
666+
@ccall jl_(x::Cint)::Cvoid
667+
end
668+
end)
669+
toplevel_eval(BareModuleTest, ex)
670+
@test @invokelatest(JuliaInterpreter.isdefinedglobal(BareModuleTest, :BareModule)) &&
671+
@invokelatest(JuliaInterpreter.isdefinedglobal(@invokelatest(BareModuleTest.BareModule), :foo))
672+
end

0 commit comments

Comments
 (0)